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

Stephane Epardaud stef at epardaud.fr
Thu Aug 31 11:54:23 EDT 2017


OK I get it: it's missing in your impl I think. It all gets done via
BuiltResponse.setEntity which sets entityClass to the class of the
entity, and then later genericType is set to the (invalid IMO)
CompletionStage<X>, but in your test, the entityClass is enough to look
up the proper marshaller, since there's no ambiguity and
CompletionStageResponseMessageBodyWriter returns true without looking at
the genericType. If it did, it would fail.

I can provide a fix and test for that too, if you want.


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/12b3f3a8/attachment.html 


More information about the resteasy-dev mailing list