[jira] [Created] (CXF-8427) Response exception mappers not invoked on MP async methods

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[jira] [Created] (CXF-8427) Response exception mappers not invoked on MP async methods

Alan Mehio (Jira)
Andy McCright created CXF-8427:
----------------------------------

             Summary: Response exception mappers not invoked on MP async methods
                 Key: CXF-8427
                 URL: https://issues.apache.org/jira/browse/CXF-8427
             Project: CXF
          Issue Type: Bug
          Components: MicroProfile
    Affects Versions: 3.4.2
            Reporter: Andy McCright
            Assignee: Andy McCright
             Fix For: 3.5.0, 3.4.3


MP Async methods have a return type of CompletionStage<?> and the exception processing should occur via the CS, not on the actual invocation of the method.  So if a response exception mapper is registered with a MP Rest Client interface, the associated exception should be on the throws clause for synchronous methods, but not necessarily for asynchronous methods.

Here's and example:

{code:java}
public interface MyClient {
  @GET
  @Path("sync")
  String getSync() throws MyCustomException;

  @GET
  @Path("async")
  CompletionStage<String> getAync();
{code}

{code:java}
public class MyCustomExceptionResponseMapper implements ResponseExceptionMapper<MyCustomException> {
    @Override
    public boolean handles(int status, MultivaluedMap<String, Object> headers) {
        return status == 499;
    }
    @Override
    public MyCustomException toThrowable(Response response) {
        return new MyCustomException();
    }
}
{code}

For sync invocation, we would expect the invocation to throw the exception:
{code:java}
try {
    myClient.getSync();
} catch (MyCustomException ex) {
    //...
}
{code}

But for async invocation, we would expect the exception to be throw from the CompletionStage<?>, like:

{code:java}
CompletionStage<String> cs = myClient.getAsync();
cs.exceptionally(ex -> {
    Throwable cause = ex.getCause(); // ex should be a CompletionException
    if (cause instanceof MyCustomException) {
        // ...
    }
});
// or
try {
    cs.toCompletableFuture().get();
} catch (ExecutionException ex) {
    Throwable cause = ex.getCause();
    if (cause instanceof MyCustomException) {
        //...
    }
}
{code}

Currently, the async flow fails because CXF is checking that the exception type is listed in the throws clause of the interface method signature.  So instead of throwing a MyCustomException wrapped in a CompletionException (or ExecutionException), it is throwing a wrapped WebApplicationException.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)