> Well, you can’t ignore the AsyncResponse either, because something has to hold the returned value. Those async methods are void.
Hmm... I believe that you can return a non-void value. On the server side, that return value would be ignored, but it should allow you to use the same interface for the client and server (assuming MP ignores the AsyncResponse parameter). > The cleanest solution would be for JAX-RS to formally support different async/reactive types as returns with some sort of @Provider. Agreed. I also think that if @Suspended could apply to instance variables (the same way the @Context does) then this problem goes away. This might be worth reporting to the Jakarta JAX-RS community. > 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. No argument here. There has been discussion about pulling in a type-safe, proxy-based client into JAX-RS ClientBuilder, but I think the process is somewhat stalled by legal (or at least non-technical) reasons... Thanks again - and good luck, Andy On Wed, Dec 26, 2018 at 4:54 PM James Carman <[email protected]> wrote: > 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? > >> > > > > >> > > > >> > > >> > > >
