[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