Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON-Jackson does not handle resource returning CompletionStage<X> #3672

Open
jerseyrobot opened this issue Sep 18, 2017 · 8 comments
Open

Comments

@jerseyrobot
Copy link
Contributor

It seems like jersey-media-json-jackson is not up to date with the latest JAX-RS 2.1 features.
I tried creating the following resource method:

@GET
@Produces({"application/json" })
@Path("async")
public CompletionStage<Hello> asyncHello(@NotNull @PathParam(value = "lang") String lang,
                                         @NotNull @Size(min = 2) @QueryParam("yo") String greet){
        return CompletableFuture.supplyAsync(() -> new Hello(lang, greet);
}

This fails with stack trace

java.lang.IllegalArgumentException: Class org.kantega.reststop.helloworld.jaxrs.Hello not subtype of [simple type, class java.util.concurrent.CompletionStage<org.kantega.reststop.helloworld.jaxrs.Hello>]
	at com.fasterxml.jackson.databind.type.TypeFactory.constructSpecializedType(TypeFactory.java:359)
	at org.glassfish.jersey.jackson.internal.jackson.jaxrs.base.ProviderBase.writeTo(ProviderBase.java:624)
	at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:266)

Returning a plain String with text/plain works as expected.

Just as a test I build my own version of Jersey with some additional code in org.glassfish.jersey.jackson.internal.jackson.jaxrs.base.ProviderBase.writeTo(...):

TypeFactory typeFactory = writer.getTypeFactory();

String typeName = genericType.getTypeName();
if(typeName.contains(CompletionStage.class.getName())) {
    Type[] actualTypeArguments = ((ParameterizedTypeImpl) genericType).getActualTypeArguments();
    genericType = actualTypeArguments[0];
}

JavaType baseType = typeFactory.constructType(genericType);

The middle part unwrapping the CompletionStage is new.
This works.

So, have I missed something, or is the CompletionStage support not complete?

@jerseyrobot
Copy link
Contributor Author

@dandew Commented
Any traction on fixing this? It's one of the very first thing you try when switching to JAX-RS 2.1 and it's sad to see it break right away 😅

@jerseyrobot
Copy link
Contributor Author

@computerlove Commented
As far as I see it should'nt be a big task to fix.
Not sure if the above fix/hack is the correct place to handle this.
It would be nice if someone could comment on if this is a acceptable solution, and if not point us in the general area where it should be handled.

@jerseyrobot
Copy link
Contributor Author

@dandew
Copy link

dandew commented May 15, 2018

@computerlove Maybe worth trying to send a PR with your proposed fix? This bug is turning into a showstopper.

@mageshwaranr
Copy link

mageshwaranr commented Oct 31, 2018

Faced the exact same problem. Following lines of code helped fixed the issue.

Made a local copy of org.glassfish.jersey.jackson.internal.jackson.jaxrs.base.ProviderBase and modified writeTo method as pointed out by @jerseyrobot .

TypeFactory typeFactory = writer.getTypeFactory(); `
// Newly added statements...  after line no : 621
if (genericType instanceof ParameterizedType ) {
    Type rawType = ((ParameterizedType) genericType).getRawType();
        if (rawType instanceof Class && CompletionStage.class.isAssignableFrom((Class)rawType)) {
            // CompletionStage has only one parameterized type. So pick the first
            genericType = ((ParameterizedType) genericType).getActualTypeArguments()[0];
        }
}
JavaType baseType = typeFactory.constructType(genericType);

I modified CompletionStageTest and found it to be working.

@computerlove
Copy link

@mageshwaranr Have you created a PR? Your snippet looks like a better version of my suggestion.

@mageshwaranr
Copy link

Just now submitted a PR just now.

@edinardo
Copy link

edinardo commented Aug 5, 2019

For who is still waiting for the official fix and don't want (or can't) repack jersey-media-json-jackson with the patch for each new version, a quick simple workaround is to implement WriterInterceptor that changes the context GenericType. Both @computerlove or @mageshwaranr proposed code can be used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants