Problems using MP Rest Client and RESTEasy

811 views
Skip to first unread message

Luca Masini

unread,
Apr 20, 2021, 6:35:46 AM4/20/21
to Quarkus Development mailing list
Hi guys, before opening issues I would like to know if my understanding of the two APIs is correct.

The arguments are
  1. REST Client Exception Handling
  2. REST Client Headers Handling
  3. REST Client Filters
I created a test-case here:


in the README I wrote what I expected from my understanding of the API and what I get.

To summurize if you don't have time to read it all:
  1. Using RESTEasy Reactive + REST Client Reactive exceptions are not handled as I expected either using a mapper or a onFailure().
  2. Using RESTEasy Reactive + REST Client Reactive also headers are not sent correctly to the downstream server using some content-type
  3. Using RESTEasy Reactive + REST Client Reactive the getEntityStream in the filter's context can be null
  4. Both with reactive and not reactive I've got problems managing exception that must be caught by the Client Exception Handler
I hope that I was clear enough for your understanding and to know if is the case of opening a new issue or change my mind about what I can expect from the API I'm using.

Thanks.

Michał Szynkiewicz

unread,
Apr 20, 2021, 3:52:17 PM4/20/21
to luca....@gmail.com, Quarkus Development mailing list
Hi Luca,

Thanks for letting us know.
Could you open github issues for the things you mentioned?

Thanks,
Michał

--
You received this message because you are subscribed to the Google Groups "Quarkus Development mailing list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to quarkus-dev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/quarkus-dev/032ca0b8-a302-479c-a61a-ede5fa6bf055n%40googlegroups.com.

Steve Bolton

unread,
Apr 20, 2021, 7:41:31 PM4/20/21
to michal.l.s...@gmail.com, luca....@gmail.com, Quarkus Development mailing list
I have actually happens to  come across the issues with error mapping when using Uni yesterday and have found a fix for it in the Quarkus code.  If there is not an issue already for this I will add it in a bit with the proposed fix.  Not sure if the other issues here are related or separate.  I did also find an issue with multipart upload when using Uni and that is an issue with the core resteasy code not passing parameter annotations.  

Luca Masini

unread,
Apr 21, 2021, 2:21:05 AM4/21/21
to Steve Bolton, michal.l.s...@gmail.com, Quarkus Development mailing list
@st...@boltn.com are you going to open the issues yourself ? Can I help you if in the meanwhile I open every single issue and then you create the PR ?
--
****************************************
http://www.lucamasini.net
http://twitter.com/lmasini
http://www.linkedin.com/pub/luca-masini/7/10/2b9
****************************************

Steve Bolton

unread,
Apr 21, 2021, 10:03:32 AM4/21/21
to Luca Masini, Steve Bolton, michal.l.s...@gmail.com, Quarkus Development mailing list
I think my fix maybe more of a workaround.  I was just disgnosing a bit more.   The problem I was having was the UniInvokerProvider was returning a wrapped CompletionStageRxInvokerImpl instead of an AsyncInterceptorRxInvoker.  The AsyncIntercerptorRxInvoker from resteasy-client-microprofile adds a finally to the CompletionStage that runs the exception mappers on the async exceptions that created with org.jboss.resteasy.microprofile.clienf.ExceptionMapping.   this leaves a HandlerException "Handled Internally" to be returned instead of WebApplicationException.

CompletionStage works fine.  My workaround was to register my own version of UniInvokerProvider that explicitly wraps a new AsyncInterceptorRxInvoker.   This is not a solution in the main code as UniInvokerProvider does not have resteasy-client-microprofile as a dependency.   I am not sure whether we should have a different subclass of ClientInvocationBuilder passed in as it is this that is specifically creating a new instance of CompletionStageRxInvokerImpl in the rx() method instead of the AsyncInterceptorRxInvoker that is needed.

Below is the workaround.  

The issue I had with uploading file was it was failing to find the MessageBodyReader when I used an Uni in my return type and was sending a MultiPartForm.   The problem is that the entity object is getting recreated in the flow of using the Uni and the the annotations list is not being passed in the argument list,  this is an issue with CompletionStage also and not specific to Quarkus.   How do we usually handle this kind of bug in quarkus the fix is in resteasy-client org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker

Example of failing rest client method.   Essentially the @MultipartForm annotation is ignored.  I have added a pull request and ticket on resteasy  https://issues.redhat.com/browse/RESTEASY-2872
@POST
@Path("feeds")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
Uni<FeedAcknowledgement> postFeeds(
@QueryParam("feedType") FeedType feedType,
@QueryParam("setupType") String setupType,
@MultipartForm MultipartBody body);

Workaround for exception handling issue
import io.quarkus.resteasy.mutiny.common.runtime.UniRxInvoker;
import io.quarkus.resteasy.mutiny.common.runtime.UniRxInvokerImpl;
import java.util.concurrent.ExecutorService;
import javax.annotation.Priority;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.client.RxInvokerProvider;
import javax.ws.rs.client.SyncInvoker;
import javax.ws.rs.ext.Provider;
import org.jboss.resteasy.client.jaxrs.internal.ClientInvocationBuilder;
import org.jboss.resteasy.microprofile.client.async.AsyncInterceptorRxInvoker;

@Provider
@Priority(1)
public class FixupUniInvokerProvider implements RxInvokerProvider<UniRxInvoker> {

@Override
public boolean isProviderFor(Class<?> clazz) {
return UniRxInvoker.class.equals(clazz);
}

@Override
public UniRxInvoker getRxInvoker(SyncInvoker syncInvoker, ExecutorService executorService) {
if (syncInvoker instanceof ClientInvocationBuilder) {
return new UniRxInvokerImpl(new AsyncInterceptorRxInvoker(syncInvoker, executorService));
} else {
throw new ProcessingException("Expected a ClientInvocationBuilder");
}
}
}
Reply all
Reply to author
Forward
0 new messages