[ 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)