Hi Stephane,
many topics here, I need to digest them a bit and check with the rest of
the team, before getting back. In the mean time, few quick answers:
* regarding JAX-RS 2.1, we have initial implementation of almost all
additions, but we're still testing and improving it. This said, it's
difficult to tell how far we are as long as the new TCK is not available
(and then we won't be giving numbers here, sorry ;-) )
* the JSR-370 EG has thought about reactive libs integration, but basically
on client side only. I'm definitely interested in exploring what we can do
on server side
* generally speaking, feel free to link any reference to your prototype,
usage scenario, examples, etc that you can share ... that helps
understanding each others
* sure, we'll be happy to process PRs ;-)
Cheers
Alessio
On Thu, Aug 10, 2017 at 9:38 AM, Stephane Epardaud <stef(a)epardaud.fr> 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