users@jersey.java.net

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

From: Jack Lista <jackalista_at_gmail.com>
Date: Mon, 13 Jan 2014 17:06:39 -0800

I got server side log file tracing turned on, it turns out that in addition
to the properties you need to set that I mentioned in my previous post, you
also have to register the LoggingFilter. I added this to my application
sublass and I now get *minor* amounts of trace info showing up:

import import org.glassfish.jersey.filter.LoggingFilter;
...
register(LoggingFilter.class);


I also tried regsitering like this:

import import org.glassfish.jersey.filter.LoggingFilter;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseFilter;
...
register(LoggingFilter.class, ContainerRequestFilter.class).
register(LoggingFilter.class, ContainerResponseFilter.class);

The effect appears the same with both means of registering the logging
filter. Unfortunately, none of the tracing, even at the VERBOSE level of
detail, is telling me what JSON marshalling / unmarshalling is being used.
I have it set to verbose, but that's not very verbose in my view, it's just
giving me a little bit about the HTTP request/response. In fact, the
runtime is barely even mentioning JSON beyond what's in accept headers
(request) and content type (response). On the response side, this is all I
see:

Jan 13, 2014 4:11:09 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 3 * Server responded with a response on thread http-bio-8080-exec-6
3 < 201
3 < Content-Type: application/json
3 < Location: http://blahblahblah...

There's also mention of the accept header in the request tracing:

4 > accept: application/json

That's it, no other mention of JSON in any form. How do I get the runtime
to tell me what JSON infrastructure I'm using?? Is there a different means
of registering the LoggingFilter that will make it spit out more info?

I am getting bi-directional databinding, I can serialize my POJOs to JSON
and can deserialize them back into java objects, but I want to see what
JSON processing I'm using, as I haven't registered any JSON provider or
feature, all I did was put the 2.3.1 Jackson dependencies in my pom.xml. I
want to do a sanity check on what I'm doing and make sure I'm not using a
horked configuration. How do I get more info on my JSON configuration?

I tried registering the following in my App (ResourceConfig) subclass, but
I'm explicitly *not* using either of these, as they both threw exceptions
when I registered them (individually, I didn't register them both at once):

...
register(JacksonFeature.class);
register(MoxyJsonFeature.class);

I'd like to figure out how I can validate that my JSON processing stuff is
properly configured, but so far I can't seem to get any visibility into
it. How do you get more info on this? Is there deeper tracing? Is there
some other means?

You know how you can set a flag in hibernate and you get more gory detail
on the SQL it's using than you could ever want? *That's* what I want here,
some module is marshaling this stuff and unmarshaling it and I want to turn
on logging in that module so I can see what module it is and what's going
on... How do you do that?

Thanks...


On Mon, Jan 13, 2014 at 3:24 PM, Jack Lista <jackalista_at_gmail.com> wrote:

> Hi Jakub, Jersey folks,
>
> I'm trying to turn on server side log file tracing to see what JSON
> databinding I'm using and am having trouble finding out how to successfully
> get actual logs to show up in a log file.
>
> I set these properties in my Application class:
>
> property("jersey.config.server.tracing", "ALL").
> property("jersey.config.server.tracing.threshold", "TRACE");
>
> Next I got an error related to headers buffer space, so I added the
> following to my tomcat's server.xml:
>
> <Connector port="8080" protocol="HTTP/1.1"
> connectionTimeout="20000"
> maxHttpHeaderSize="16384" <------------I added this,
> and the error stopped
> redirectPort="8443" />
>
> I'm pretty sure now that logging/tracing is now turned on, but I still
> don't see anything. Where is this logging supposed to show up? I'm not
> seeing it in catalina.out, is this stuff directed to a different log file?
>
> I've seen chapter 19 (Tracing and Monitoring) here:
>
>
> https://jersey.java.net/documentation/latest/monitoring_tracing.html#tracing
>
> It says that that there's a "dedicated logger" for java for server side
> log file tracing, but what do you actually have to do to make it log
> things? I have been scouring the web for details and there are a few pages
> but they all seem to be relevant to Jersey 1.x and don't seem applicable.
> What do you have to do to get the trace info to show up in a server side
> log file?
>
>
> On Thu, Jan 9, 2014 at 8:53 AM, Jakub Podlesak <jakub.podlesak_at_oracle.com>wrote:
>
>> Hi Jack,
>>
>> ad 1) it is hard to tell from the information you provided.
>> Anyway, you should be able to determine the effective worker used
>> if you set Jersey’s server side config property,
>> jersey.config.server.tracing,
>> to “ALL”. Then the actual worker used at runtime should get
>> logged.
>>
>> ad 2) i guess this is rather a question for Jackson mailing list, if it
>> turns out one of the Jackson
>> providers is used and the annotation is not mandated. Let’s clarify
>> the first thing first.
>>
>> Cheers,
>>
>> ~Jakub
>>
>>
>> On 08 Jan 2014, at 17:53, Jack Lista <jackalista_at_gmail.com> wrote:
>>
>> And yes, your more compact syntax works nicely, thank you very much! If
>> you wouldn't mind, would you please answer those two dumb questions about
>> 1.) which databinding I'm actually using and 2.) the question about
>> @JsonIgnore?
>>
>> Much thanks sir...
>>
>> -=j=-
>>
>>
>> On Wed, Jan 8, 2014 at 8:20 AM, Jack Lista <jackalista_at_gmail.com> wrote:
>>
>>> Ah, yes! Sweet! So *that's* how you submit a generic type to this
>>> infrastructure!! I had stumbled across something very similar, although a
>>> bit more long winded, as the last thing I tried last night, but I just
>>> happened across it based on a comment of the guy I'm working with on this
>>> and I tried it and it actually then gave me my wrapper envelope back with
>>> my domain class(es) inside it. Here's the syntax I tried last night which
>>> worked (& I'm going to try your more compact form immediately):
>>>
>>> GenericType<ResponseEnvelope<FooBar>> fooResponseEnvType = new
>>> GenericType<ResponseEnvelope<FooBar>>() {};
>>>
>>> // then pass fooResponseEnvType to the get(...) method like so:
>>>
>>> ResponseEnvelope<FooBar> envelope4ReuseMkt = client.target("
>>> http://localhost:8080/v1.1/rs")
>>> .path("foobar")
>>> .path(fooBarId.toString())
>>>
>>> .request(MediaType.APPLICATION_JSON_TYPE)
>>> .get(fooResponseEnvType);
>>>
>>> Thanks so much for your comment, however, as your code is much more
>>> compact which I like. Where, pray tell, is this stuff documented? Almost
>>> *everyone* is using domain objects (or DTOs, etc.) with these services, so
>>> the examples with simple String data types aren't representative of the
>>> techniques needed to work with domain objects, generic types and other
>>> things commonly found in enterprise environments (like the GenericType
>>> utility class you pointed out). We have a pretty crazy domain model, so I
>>> am going to need to get much more deeply into things like this, where is
>>> this GenericType utility discussed, beyond a javadoc?
>>>
>>> I would also *really* love to understand what such facilities exist, how
>>> they're intended to be used, what kids of functionality is currently
>>> support and even, if you guys know, what direction things are headed in.
>>> I've been over (I think) most of the
>>> https://jersey.java.net/documentation/latest... site but I haven't
>>> found discussion of things like GenericType, sorry if I'm being dense but
>>> can you point that out? (Thanks again.)
>>>
>>> While I have your ear, can you answer two relatively simple questions?
>>> My services are working when I don't explicitly register any JSON Features
>>> at all, but I do have these mvn dependencies in my pom.xml:
>>>
>>>
>>> <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>
>>>
>>> What JSON databinding am I using? If I explicitly enable the
>>> JacsonFeature, I get very different behavior (stackoverflow errors).
>>>
>>> The second dumb question is, is the @JsonIgnore annotation in domain
>>> classes still how you are supposed to prevent recursive stackoverflow JSON
>>> serialization errors? I ask because if I explicitly enable the
>>> JacksonFeature as I described in my post, I would assume that I am
>>> definitely using Jackson but the @JsonIgnore annotations within my domain
>>> classes appear to be ignored themselves and I suffer stackoverflow
>>> errors. We have a very complex domain model so I want to stay on top of
>>> the best techniques for managing domain classes that have a lot of
>>> relationships among them.
>>>
>>> Thanks Jakub, appreciate your help *immensely*!
>>>
>>> -=j=-
>>>
>>>
>>>
>>> On Wed, Jan 8, 2014 at 5:30 AM, Jakub Podlesak <
>>> jakub.podlesak_at_oracle.com> wrote:
>>>
>>>> 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
>>>>
>>>>
>>>>
>>>
>>
>>
>