users@jersey.java.net

[Jersey] Re: Client config (?) or other databinding problems in composition context

From: Jakub Podlesak <jakub.podlesak_at_oracle.com>
Date: Wed, 8 Jan 2014 14:30:09 +0100

Hi Jack,

Please try to use the following type when reading the entity:

ResponseEnvelope<FooBar> envelope = svcResponse.readEntity(new javax.ws.rs.core.GenericType<ResponseEnvelope<FooBar>>(){});

Does it help?

~Jakub


On 07 Jan 2014, at 22:05, Jack Lista <jackalista_at_gmail.com> wrote:

> Hi,
>
> I'm trying to get a composition working in which I'm having trouble getting my entity back from the Response even though the actual service request seems to have succeeded. I'm using Jersey 2.5.1 and am using the client API to have one service call another 2 services and then do some processing based on the results of the 2 composed services.
>
> I'm having no trouble getting the two services being composed to work, marshaling the POJO service payload as JSON. If I call either service in a browser they both work and spit out the appropriate JSON content. Additionally, when I call them from within the composing service, it appears that the calls have succeeded. Printing the Response via a logger shows the following:
>
> svcResponse: InboundJaxrsResponse{ClientResponse{method=GET, uri=http://localhost:8080/v1.1/rs/foobar/1, status=200, reason=OK}}
>
> Additionally, if I call (Response) svcResponse.hasEntity() I get a result of true.
>
> However, when I try to call readEntity(), I get a class cast exception:
> java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.baz.domain.FooBar
>
> A few details of my implementation that may be relevant are that we are using an application class that subclasses ResourceConfig (without a web.xml). This app class also uses the following package scanning call to find our annotated classes:
>
> packages("com.baz.rest");
>
> The POJO domain model classes being returned are not in that package, as the above snippet of stacktrace shows, but they are being marshaled to JSON without issue, so I suspect that's not a problem.
>
> I'm not registering any JSON provider, but have the following in my pom.xml which seems to have enabled Jackson:
>
> <dependency>
> <groupId>com.fasterxml.jackson.core</groupId>
> <artifactId>jackson-databind</artifactId>
> <version>${jackson.version}</version>
> </dependency>
>
> <dependency>
> <groupId>com.fasterxml.jackson.core</groupId>
> <artifactId>jackson-annotations</artifactId>
> <version>${jackson.version}</version>
> </dependency>
>
> I have also tried using the following in my pom.xml but it seems to make no difference whether it's present or not:
>
> <dependency>
> <groupId>org.glassfish.jersey.media</groupId>
> <artifactId>jersey-media-json-jackson</artifactId>
> </dependency>
>
> It is necessary for compilation if I explicitly register the JacksonFeature, but seems to have no effect otherwise.
>
> I'm using a simple unadorned client created in the composing service (the one that is calling the other two services):
>
> Client client = ClientBuilder.newClient();
>
> I'm also creating a webTarget and an invocation in the following manner:
>
> WebTarget webTarget = client.target("http://localhost:8080/v1.1/rs");
> Invocation.Builder invocationBuilder = webTarget
> .path("foobar")
> .path(foobarId.toString())
> .request(MediaType.APPLICATION_JSON_TYPE);
> Response svcResponse = invocationBuilder.get(Response.class);
>
>
> I've tried explicitly enabling Jackson by adding the following call in my application subclass:
>
> register(JacksonFeature.class);
>
> and adding a similar call in the client code like this:
>
> Client client = ClientBuilder.newClient().register(JacksonFeature.class);
>
> However, when I configure the server and client that way, the Jackson databinding doesn't respect the @JsonIgnore annotations in our domain model and suffers a stackoverflow error. Without that explicit configuration, I get nice decent sized chunks of JSON which do respect the @JsonIgnore annotations in our domain model. I've also tried to switch to the Moxy JSON code by adding "register(MoxyJsonFeature.class);" to the application class and calling "Client client = ClientBuilder.newClient().register(MoxyJsonFeature.class);" in the client code but this simply results in 500 errors even when calling the 2 composed services in a browser. When I do no configuration in either the application subclass or in the client code in the calling service as originally shown above, I get the proper JSON representation in a browser from each of the two composed services.
>
> The problem occurs when I try to access the entity from the response. This first call succeeds:
>
> ResponseEnvelope<FooBar> envelope = svcResponse.readEntity(ResponseEnvelope.class);
>
> However, I get the class cast exception referencing a LinkedHashMap (?!?) when I try the following call:
>
> FooBar fooBar = envelope.getPayload();
>
> Perhaps the problem is related to our envelope class that has a generic domain class embedded in it? However, Jackson has no trouble marshaling the ResponseEnvelope to JSON, so why would it fail in the opposite direction?
>
> I'm utterly confused (obvious? lol), any help would be *greatly* appreciated!
>
> --j