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(a)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(a)lists.jboss.org
>>
https://lists.jboss.org/mailman/listinfo/resteasy-dev
>
>
>
> _______________________________________________
> resteasy-dev mailing list
> resteasy-dev(a)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(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/resteasy-dev