Of course, having first-class support for client proxies (like MP has done, thank goodness) in the JAX-RS spec is key to this whole thing. On Wed, Dec 26, 2018 at 5:50 PM James Carman <[email protected]> wrote:
> Well, you can’t ignore the AsyncResponse either, because something has to > hold the returned value. Those async methods are void. The cleanest > solution would be for JAX-RS to formally support different async/reactive > types as returns with some sort of @Provider. This would be kind of a > hybrid between a MessageBodyReader and the RxInvoker stuff. You’d likely > need support for both single and stream types. Perhaps the > MessageBodyReader is the right answer, but it seemed odd since it won’t be > called until the response is received, which is too late for truly > asynchronous stuff. > > Maybe my usage is just odd, but it sure does make our microservices work > simpler in a JVM-to-JVM scenario by having that shared API interface the > server and client can both use. The JAX-RS spec seems really close, but a > bit all over the place here (AsyncResponse, AsyncInvoker, RxInvoker, oh > my). > > For our usage, we are only really focused on the response bodies. Non-2xx > status codes yield an exception with CXFs ResponseExceptionMapper when > using the client proxies for non-Response return types. > > Of course, maybe I just don’t understand this stuff at all and have just > stumbled upon something that seemingly works, but might be ill-advised. > On Wed, Dec 26, 2018 at 5:32 PM Andy McCright <[email protected]> > wrote: > >> Thanks for the feedback. I'll suggest that the next version of MP Rest >> Client should ignore AsyncResponse parameters. That way, a client app >> could pass null for that argument, and everything should still work. It is >> still a little "hacky", but I think the best solution is to use a separate >> interface for the client than the server (though I agree that there is >> some >> convenience in using the same interface for both). >> >> As for returning Response objects vs strongly typed objects, I don't think >> there is a recommendation either way. Both work - it will depend on the >> use case (like whether you need more information that what is in the >> response body - i.e. do you need to know the response code? or any of the >> header values? etc.). >> >> Thanks, >> >> Andy >> >> On Wed, Dec 26, 2018 at 4:14 PM James Carman <[email protected]> >> wrote: >> >> > Hmmmm, we have been using the same interface on both the server and >> client. >> > We publish an API jar (a separately-maintained artifact) for our >> callers to >> > use to talk to us and it makes interoperability a snap. This is using >> just >> > the CXF-specific stuff, but this AsyncRespone problem has plagued us, >> so I >> > was just curious if MP had solved it. If we could use >> CompletionStage<T> on >> > both the server and client, that’d be great. I’ve implemented that with >> a >> > MessageBodyWriter in the past, but wasn’t terribly happy with it. It >> > worked, but felt sort of “hacky”. >> > >> > I’m also not a big fan of using Response objects as the return type, >> since >> > it doesn’t help folks understand what’s going on as much as >> strongly-typed >> > responses. Is that the suggested pattern to use for MP folks? >> > On Wed, Dec 26, 2018 at 4:56 PM Andy McCright < >> [email protected] >> > > >> > wrote: >> > >> > > Hi James, >> > > >> > > The client shouldn't know or care whether the service method is async >> or >> > > not - in fact, it shouldn't care whether the remote service is using >> > JAX-RS >> > > or even Java at all. >> > > >> > > So whether you have a JAX-RS service method that looks like this: >> > > @Path("/mypath") >> > > public class MyResource { >> > > >> > > @POST >> > > @Path("sync") >> > > public Response postSync(MyEntity entity) { // do something >> > > synchronously ... } >> > > >> > > // or this: >> > > >> > > @POST >> > > @Path("async") >> > > public void postAsync(@Suspended AsyncResponse ar, MyEntity >> entity) { >> > > // return something via async response ... } >> > > } >> > > >> > > your MP Rest Client interface should look like this: >> > > >> > > @Path("/mypath") >> > > public interface MyClient { >> > > >> > > @POST >> > > @Path("sync") >> > > public Response postSync(MyEntity entity); >> > > >> > > @POST >> > > @Path("async") >> > > public Response postAsync(MyEntity entity); >> > > } >> > > >> > > Notice that the return type is the same in both cases - and that the >> > > signature on the client methods do not include an AsyncResponse >> argument. >> > > >> > > Keep in mind that in both cases, only the server is running >> > > asynchronously. The client will block for both methods. IMO, this is >> > less >> > > valuable than using async on the client. I don't really see much >> point >> > in >> > > using async on the server unless your thread pool for handling JAX-RS >> > > service methods is severely constrained. But I think async on the >> client >> > > makes a lot more sense. To do that, you would need to use MP Rest >> Client >> > > 1.1 (1.0 doesn't have async support), and then the client method >> should >> > > return an instance of CompletionStage. So if you were to convert the >> > > client above to run async, it would look like this: >> > > >> > > @Path("/mypath") >> > > public interface MyClient { >> > > >> > > @POST >> > > @Path("sync") >> > > public CompletionStage<Response> postSync(MyEntity entity); >> > > >> > > @POST >> > > @Path("async") >> > > public CompletionStage<Response> postAsync(MyEntity entity); >> > > } >> > > >> > > Hope this helps, >> > > >> > > Andy >> > > >> > > >> > > On Sat, Dec 22, 2018 at 10:24 AM James Carman < >> > [email protected]> >> > > wrote: >> > > >> > > > With the Microprofile client support, what happens if I have an >> async >> > > > service method (with @Suspended and what not)? How would I call it >> > using >> > > > the proxy object? >> > > > >> > > >> > >> >
