[ 
https://issues.apache.org/jira/browse/CXF-6373?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14512837#comment-14512837
 ] 

iris ding commented on CXF-6373:
--------------------------------

The test Failed.

After analysis, I found out we only call asyncResponseImpl.setUnmappedThrowable 
if 
the exception is thrown from ServiceInvokerInterceptor and no mapper found for 
this exception: 

ServiceInvokerInterceptor.handleMessage() -> JAXRSInvoker.invoke -> 
JAXRSInvoker.handleAsyncResponse -> JAXRSInvoker.handleAsyncFault

However in above case, the exception is thrown after ServiceInvokerInterceptor 
but in JAXRSOutInterceptor.serializeMessage().  Then the completioncallback can 
not get the correct 'Throwable"


The proposed fix is:
in JAXRSDefaultFaultOutInterceptor.handleMessage() method add below lines:

 final Fault f = (Fault) message.getContent(Exception.class);

        Response r = JAXRSUtils.convertFaultToResponse(f.getCause(), message);
       // proposed change end
        if (r == null) //which means it is an unmapped exception
        {
            try {
                AsyncResponseImpl asyncResponse = (AsyncResponseImpl) 
message.getExchange().getInMessage().get(AsyncResponse.class);
                if (asyncResponse != null)
                {
                    asyncResponse.setUnmappedThrowable(f.getCause());
                }
            } catch (Exception e)
            {//donothing

            }
        }
       //proposed change end
        if (r != null) {...........}}


After this, the test passed!!



> CompletionCallback can not get the Throwable if error occurs in other 
> interceptor (no serviceinvokerInterceptor)
> ----------------------------------------------------------------------------------------------------------------
>
>                 Key: CXF-6373
>                 URL: https://issues.apache.org/jira/browse/CXF-6373
>             Project: CXF
>          Issue Type: Bug
>          Components: JAX-RS
>    Affects Versions: 3.0.3, 3.0.4, 2.7.15
>            Reporter: iris ding
>
> //Resource class
> @Path("resource")
> public class Resource {
>    private static final AsyncResponseBlockingQueue[] step = {
>            new AsyncResponseBlockingQueue(1),
>            new AsyncResponseBlockingQueue(1),
>            new AsyncResponseBlockingQueue(1)};
>    @GET
>    @Path("suspend")
>    public void suspend(@Suspended AsyncResponse asyncResponse) {
>       step[0].add(asyncResponse);
>         }
>         
>    @GET
>    @Path("register")
>    public String registerObject(@QueryParam("step") String step) {
>       AsyncResponse async = takeAsyncResponse(step);
>       boolean b = async.register(new MyCompletionCallback()).isEmpty();
>       addResponse(async, step);
>       return b ? TRUE : FALSE;
>    }
>    
>    @GET
>    @Path("exception")
>    public String throwExceptionOnAsyncResponse(
>            @QueryParam("step") String step) {
>       System.out.println("********throwExceptionOnAsyncResponse");
>       AsyncResponse async = takeAsyncResponse(step);
>       System.out.println("*****async is not null: " + async);
>       boolean b = async.resume(new ExceptionThrowingStringBean(
>               "throw exception"));
>       System.out.println("execuet finished for resume!!!");
>       addResponse(async, step);
>       return b ? TRUE : FALSE;
>    }
>    }
>    
> ///////  StringBean
>    public class StringBean {
>    private String header;
>    public String get() {
>       return header;
>    }
>    public void set(String header) {
>       this.header = header;
>    }
>    @Override
>    public String toString() {
>       return "StringBean. To get a value, use rather #get() method.";
>    }
>    public StringBean(String header) {
>       super();
>       this.header = header;
>    }
> }
> /////// Throw Exception here
>  public class ExceptionThrowingStringBean extends StringBean {
>    public ExceptionThrowingStringBean(String header) {
>       super(header);
>    }
>    @Override
>    public String get() {
>       throw new RuntimeException(new IOException(super.get()));
>    }
> }
> ////// Register a provider to deal with StringBean, 
> // This cause we have an exception thrown in JaxrsOutInterceptor
> @Provider
> public class StringBeanEntityProvider implements 
> MessageBodyReader<StringBean>,
>         MessageBodyWriter<StringBean> {
>    @Override
>    public boolean isWriteable(Class<?> type, Type genericType,
>                               Annotation[] annotations, MediaType mediaType) {
>       return StringBean.class.isAssignableFrom(type);
>    }
>    @Override
>    public long getSize(StringBean t, Class<?> type, Type genericType,
>                        Annotation[] annotations, MediaType mediaType) {
>       return t.get().length();
>    }
>    @Override
>    public void writeTo(StringBean t, Class<?> type, Type genericType,
>                        Annotation[] annotations, MediaType mediaType,
>                        MultivaluedMap<String, Object> httpHeaders,
>                        OutputStream entityStream) throws IOException,
>            WebApplicationException {
>       entityStream.write(t.get().getBytes());
>    }
>    @Override
>    public boolean isReadable(Class<?> type, Type genericType,
>                              Annotation[] annotations, MediaType mediaType) {
>       return isWriteable(type, genericType, annotations, mediaType);
>    }
>    @Override
>    public StringBean readFrom(Class<StringBean> type, Type genericType,
>                               Annotation[] annotations, MediaType mediaType,
>                               MultivaluedMap<String, String> httpHeaders, 
> InputStream entityStream)
>            throws IOException, WebApplicationException {
>       String stream = JaxrsUtil.readFromStream(entityStream);
>       StringBean bean = new StringBean(stream);
>       return bean;
>    }
> }
> //////  Need to get the exception throwed from 
> ExceptionThrowingStringBean.get() method in this callback
> public class MyCompletionCallback implements CompletionCallback {
>    private static String throwableName;
>    public static final String NULL = "NULL";
>    public static final String NONAME = "No name has been set yet";
>    @Override
>    public void onComplete(Throwable throwable) {
>          
>       throwableName = throwable == null ? NULL : throwable.getClass()
>               .getName();
>    }
>    public static final String getLastThrowableName() {
>       return throwableName;
>    }
>    public static final void resetLastThrowableName() {
>       throwableName = NONAME;
>    }
> }



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to