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

Stephane Epardaud stef at epardaud.fr
Thu Aug 31 11:42:25 EDT 2017


Well, I guess that can't be that part. I'm talking about a resource
method returning an entity of type CompletionStage<X>, and where we look
up marshallers for X and not CompletionStage<X>. In
CompletionStageResponseConsumer you do:

         jaxrsResponse.setGenericType(method.getGenericReturnType());

Which can't be right, unless method.getGenericReturnType() is already
unwrapped to X and not CompletionStage<X>, but I haven't found where. Or
is this unwrapped later?


On 23/08/17 23:24, Ron Sigal wrote:
>
> Hi Stephane,
>
> It looks like I missed this email - I was on PTO on 8/11. Are you
> referring to
>
>>       else if (entity instanceof Response)
>>       {
>>          Response r = (Response) entity;
>>          Headers<Object> metadata = new Headers<Object>();
>>          metadata.putAll(r.getMetadata());
>>          builtResponse = new BuiltResponse(r.getStatus(),
>> r.getStatusInfo().getReasonPhrase(), metadata, r.getEntity(), 
>> method.getMethodAnnotations());
>>       }
>
> in
> org.jboss.resteasy.core.CompletionStageResponseConsumer.createResponse()?
> Is this still an issue?
>
> -Ron
>
>
> On 08/11/2017 08:12 AM, Stephane Epardaud wrote:
>>
>> OK I am looking at ResourceMethodInvoker and
>> CompletionStageResponseConsumer and will work on a PR to support
>> other async types first. Should be the easiest. What you're doing in
>> CompletionStageResponseConsumer looks _a lot_ like what I had to do
>> to support it myself in my proto. Except the bit where I have to
>> change the jaxrsResponse.setGenericType because otherwise I get
>> CompletionStage<X>.class instead of X.class when I'm looking up
>> marshallers. Since it appears you do test this, I assume it's
>> somewhere else?
>>
>>
>> On 10/08/17 19:18, Ron Sigal wrote:
>>>
>>> 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)
>>>
>>>
>>> _______________________________________________
>>> resteasy-dev mailing list
>>> resteasy-dev at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/resteasy-dev
>>
>>
>>
>> _______________________________________________
>> 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)
>
>
> _______________________________________________
> resteasy-dev mailing list
> resteasy-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/resteasy-dev

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


More information about the resteasy-dev mailing list