[resteasy-dev] Extending Resteasy async support (server-side)

Ron Sigal rsigal at redhat.com
Thu Aug 10 13:18:36 EDT 2017


Hi Stephane,

Wow, that's a lot to digest. ;-)

Have you seen the treatment of CompletionStage in 
org.jboss.resteasy.core.ResourceMethodInvoker. If the resource method 
return type is CompletionStage, ResourceMethodInvoker registers a 
org.jboss.resteasy.core.CompletionStageResponseConsumer that waits for a 
response. CompletionStage is hard coded here, but maybe we could use 
service loading and a ContextResolver to get a method that

   1. verifies that a given class has asynchronous behavior, and
   2. constructs an appropriate object like 
CompletionStageResponseConsumer to listen for a completed response.

I'll go on to try to digest the rest of your message, but that's a 
start, I hope.

-Ron


On 08/10/2017 03:38 AM, Stephane Epardaud wrote:
> Hi,
>
> I'm working on trying to make Resteasy and Vertx integrate better, and 
> while writing a prototype I noticed several things which would need 
> support from Resteasy.
>
> The first thing which I need RE to support is that I want to be able 
> to return async types from my resource methods. In JAX-RS 2.0 async 
> resource methods are supported but require a peculiar style, such as 
> taking a "@Suspended AsyncResponse asyncResponse" parameter, returning 
> void, and resuming with asyncResponse.resume(entityOrException).
>
> I know JAX-RS 2.1 supports CompletionStage<Response>. This is great, 
> but it doesn't define a pluggable API to support other types such as 
> rxJava. We should really make that be pluggable, so that I can use 
> rx.Single or other async frameworks.
>
> ATM I have a prototype which supports CompletionStage and rx.Single, 
> without modifying RE, but it's using CDI validators to intercept the 
> returned value and do the plugging, which is a terrible hack. I 
> couldn't find a way to do this properly with RE because I can't 
> intercept the returned value before it's sent to the marshallers, by 
> which time it's too late to mark the response as async and register on 
> the listeners.
>
> Now, because the return type is CompletionStage<X> (or rx.Single<X> 
> doesn't matter), the ResourceMethodInvoker.getGenericReturnType() 
> returns a very unhelpful type, which I can't used to look up the 
> proper marshallers, so again this is something that has to be taken 
> into account.
>
> Sometimes I will declare a return type of CompletionStage<Object> 
> because Java doesn't have Union Types and I can't declare it as 
> CompletionStage<Response | MyEntity>, and in that case I have to look 
> up marshallers based on the entity instance's class rather than the 
> declared type. I suppose the same applies to non-async return types. 
> Is it the spec that fixes this looking up of marshallers based on the 
> static return type and not the entity's actual type?
>
> Now, I haven't said much about things like Observable or Flowable 
> (async types that emit more than one value), because it's not yet 
> clear in my mind how that would work with RE. In my proto I do support 
> returning such flows and based on how the method is annotated, RE will 
> pick one strategy:
>
> - collect all values in a java.util.List and when all done proceed,
> - send them as HTTP Chunked: marshall and send each value as they are 
> made available
> - send them as server-sent events but that's a bit weird when it's not 
> plain text
>
> Since JAX-RS 2.1 supports server-sent events, that would also be a 
> strategy that makes sense.
>
> I have contacted the CDI team to discuss async injection, because I 
> also want to be able to inject instances of X in my resources where 
> there only exists providers of type CompletionStage<X>, which requires 
> a new CDI API to support async resource instantiation/injection. 
> If/when that gets added to CDI, RE will need to be updated to support 
> this async injection.
>
> Similarly I also have a problem with interceptors, because sometimes 
> my RE interceptors require resolving of async types before they can go 
> on with the request. For example for authentication or sessions my 
> interceptors have to wait for vert.x to resolve async values before I 
> can check them and proceed with the requests. The wait the interceptor 
> API is written doesn't let me suspend interception. It's be great if 
> it could. Alternately CDI interceptors have an InvocationContext 
> parameter given to the interceptor on which you have to call proceed() 
> in order to proceed. This allows me to delay proceeding until I have 
> all my async values resolved and only then proceed with the call to 
> the next interceptor. That'd work too.
>
> And I guess the same applies to Marshallers. I have Template entity 
> objects that I need to marshall and that is done via an async API in 
> vertx, so again I can't entirely marshall the response when the 
> marshaller is called.
>
> Last, and least interestingly, I've always been bitten by the fact 
> that ExceptionMappers are global and I can't override them per 
> resource. Sometimes I have UI/HTML resources that need exception 
> mappers that forward to UI pages, and API resources that have to 
> serialise errors into JSON. I've added support for an 
> @WithExceptionMapper(Class<? extends ExceptionMapper>) annotation that 
> you can place on the resource method or class to override the error 
> mapper for this call.
>
> WDYT?
>
> I'm definitly game for pushing PRs for those things, BTW.
>
> How far along are you guys with implementing JAX-RS 2.1 in RE?
>
> Cheers.
>
>
> _______________________________________________
> resteasy-dev mailing list
> resteasy-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/resteasy-dev

-- 
My company's smarter than your company (unless you work for Red Hat)

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/resteasy-dev/attachments/20170810/64bec31a/attachment-0001.html 


More information about the resteasy-dev mailing list