users@jersey.java.net

[Jersey] Re: JAXB and Jackson annotations together

From: Brian Mulholland <blmulholland_at_gmail.com>
Date: Thu, 5 Jul 2012 14:29:06 -0400

>> Brian said:
>> I am trying to write a Jersey service (and test client) that consumes
>> the same bean hierarchy as json or xml (users choice). I did json
>> first using Jackson annotations, and it worked perfectly. I did XML
>> next using JAXB annotations added onto the Jackson ones in the beans,
>> again, worked perfectly.
>>
>> However, when both annotations exist, the JSON stuff fails. The
>> request launches, but I get UnrecognizedPropertyException on the
>> server. The message is "Unrecognized field <fieldName> (Class
>> <myClass>), not marked as ignorable." The field it blows up on is an
>> array of sub-beans, which again, works FINE when I run with Jackson
>> annotations alone.
>>
>> Why does the presence of JAXB annotations throw everything wonky? And
>> how can I make them coexist peacefully?

> Tatu said:
> There are two basic possibilities -- either Jackson's combined
> annotation introspector handling has an issue, or it is due to Jersey
> configuration.

Okay, the problem is definitely with Jersey when both JAXB and Jackson
annotations are present. I wrote a test method that did the following
(no jersey) and it worked fine, so Jackson appears to work even with
both annotations.

                BeanParent parent = prepObj();
                ObjectMapper mapper = new ObjectMapper();
                String jsonString = mapper.writeValueAsString(parent);
                BeanParent other = mapper.readValue(jsonString, BeanParent.class);
                assertSame(parent, other);

> If you can reproduce the issue outside of Jersey with just Jackson
> (configured to use both annotations), it would be easier to figured
> out the problem.

Unfortunately, the opposite appears to be true. Outside Jersey it
works fine with the same annotations. I also changed my Jersey method
to accept and return a String, so that Jersey will not try to
translate it, and then use Jackson manually inside the method. This
worked flawlessly. So that gives me a viable workaround, though I
really would prefer the cleanliness of letting jersey handle it.

> One possible source of problems is that semantics of JAXB annotations
> differs a bit from that of Jackson's native handling; especially with
> Jackson versions prior to 1.9. This could cause problems when JAXB
> annotations are only added on getter or setter, not both. But this is
> just one possibility.

I was using 1.8.3, but I upgraded to 1.9.8 and get the same behavior.
I DO in fact have @XmlElement and @XmlAttribute only on get methods,
when I tried to put them on both, JAXB broke, and it did not help
Jackson. Same exact error. Note that when I use the Jersey CLIENT in
my test methods, it works (IOW, it doesn't fail until it reaches the
service, which then exceptions and returns error). The client looks
like the following.

                ClientConfig config = new DefaultClientConfig();
                config.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING,
Boolean.TRUE);
                config.getClasses().add(JacksonJsonProvider.class);
                Client client = Client.create(config);
                WebResource service = client.resource(getBaseURI());
                BeanParent parent = prepObj();
                ClientResponse response = service.path("marshal")
                                                                         .path("json")
                                                                         .accept(MediaType.APPLICATION_JSON)
                                                                         .type(MediaType.APPLICATION_JSON_TYPE)
                                                                         .post(ClientResponse.class, parent);

In terms of server Jersey configuration, all I do is configure the
pojomapping feature to true in web.xml. AFAIK, no other relevant
configurations differ. I presume that the reason this works on the
client is that I configured the JacksonJsonProvider explicitly? Is
there a way I can do something equivalent in web.xml? I saw something
similar online. People suggested adding org.codehaus.jackson.jaxrs to
the packages to scan, but that made no difference, perhaps since the
JAXB one is in the same package. Perhaps those posts are dated. Is
there some other mechanism?

Brian Mulholland
"For every complex problem, there is an answer that is clear, simple and wrong."
--H.L. Mencken
"Politics is the art of looking for trouble, finding it everywhere,
diagnosing it incorrectly, and applying the wrong remedies."
--Groucho Marx