Uploaded image for project: 'CXF'
  1. CXF
  2. CXF-8427

Response exception mappers not invoked on MP async methods

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Minor
    • Resolution: Fixed
    • 3.4.2
    • 3.5.0, 3.4.3
    • MicroProfile
    • None
    • Unknown

    Description

      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:

      public interface MyClient {
        @GET 
        @Path("sync")
        String getSync() throws MyCustomException;
      
        @GET 
        @Path("async")
        CompletionStage<String> getAync();
      
      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();
          }
      }
      

      For sync invocation, we would expect the invocation to throw the exception:

      try {
          myClient.getSync();
      } catch (MyCustomException ex) {
          //...
      }
      

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

      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) {
              //...
          }
      }
      

      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.

      Attachments

        Activity

          People

            amccright Andy McCright
            amccright Andy McCright
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: