On Tue, Mar 23, 2010 at 03:14:13PM +0100, Paul Sandoz wrote:
>
> On Mar 23, 2010, at 1:51 PM, Jakub Podlesak wrote:
>
> >
> >Hi Alex,
> >
> >could you please zip the web application and send it to me?
> >If it is too big, please send it privately (to jakub.podlesak at
> >sun.com).
> >
>
> I think what is going on here is the Jersey JSON JAXB serialization
> requires that what are defined to be XML attributes in the XML
> serialization occur first in the JSON serialization. Namely when JAXB
> marshalls out stuff it will marshall out the set of attributes first.
> When JAXB unmarshalls it expects the set of attributes first.
That's exactly what happens here. I oversaw the @XmlAttribute annotations.
Thanks, Paul, for pointing this out!
JSON/JAXB procesor needs all "attributes" to come first. One solution
would be to convert the attributes to elements (s/_at_XmlAttribute/_at_XmlElement/).
Another one to switch to the Jackson provider, which does not use JAXB.
>
> My guess is you can change the order of the information marked as XML
> attributes but not intermix these with the information marked as XML
> elements.
Right,
~Jakub
>
> Paul.
>
>
> >Thanks,
> >
> >~Jakub
> >
> >On Tue, Mar 23, 2010 at 11:18:44AM +0000, Alex Treppass wrote:
> >>The web service I am writing using Jersey / JAXB plays perfectly with
> >>@Consuming and @Producing XML from JAXB-annotated POJOs. However when
> >>working with JSON, JAXB (or Jersey?) seems to require a brittle
> >>ordering of
> >>JSON elements. I am using Jersey 1.1.5 and JaxB 2.2 ri-20091104
> >>(latest).
> >>
> >>I've created a simple Web application project to demonstrate:
> >>
> >>POJO
> >>---------------
> >>@XmlRootElement(name = "Test")
> >>@XmlAccessorType(XmlAccessType.FIELD)
> >>public class Test
> >>{
> >> @XmlAttribute
> >> private int int1;
> >> @XmlElement
> >> private String string1;
> >> @XmlElement
> >> private List<String> strings;
> >> @XmlAttribute
> >> private int int2;
> >> @XmlAttribute
> >> private long long1;
> >>
> >> public Test()
> >> {
> >> super();
> >> }
> >>
> >> public Test(int int1, String string1, List<String> strings, int
> >>int2,
> >>long long1)
> >> {
> >> super();
> >> this.int1 = int1;
> >> this.int2 = int2;
> >> this.long1 = long1;
> >> this.string1 = string1;
> >> this.strings = strings;
> >> }
> >>
> >> ... hashcode & equals omitted.
> >>}
> >>
> >>Interface
> >>---------------
> >>@Path("test")
> >>public interface IView
> >>{
> >> @GET
> >> @Path("get/")
> >> @Produces(MediaType.APPLICATION_JSON)
> >> public abstract Test getTest();
> >>
> >> @POST
> >> @Path("post/")
> >> @Consumes(MediaType.APPLICATION_JSON)
> >> @Produces(MediaType.APPLICATION_JSON)
> >> public abstract Test takeTest(final Test test);
> >>}
> >>
> >>Implementation
> >>---------------
> >>@Provider
> >>public class View implements IView
> >>{
> >> public Test getTest()
> >> {
> >> return new Test(1, "string", Arrays.asList(new String[]
> >>{ "s1", "s2"
> >>}), 2, 3L);
> >> }
> >>
> >> public Test takeTest(final Test test)
> >> {
> >> return test;
> >> }
> >>}
> >>
> >>When I request /test/get, JAXB returns me the following JSON every
> >>time,
> >>even though I have no @XmlType(propOrder =) class annotation set.
> >>This is
> >>fine - I don't mind an arbitrary ordering for output.
> >>(Note that I am using a custom ContextResolver<JAXBContext> to read &
> >>return JSONConfiguration.natural() notation for my Test class)
> >> {"int1":1,"int2":2,"long1":3,"string1":"string","strings":
> >>["s1","s2"]}
> >>
> >>However, when I try and consume JSON that does not match this
> >>order, strange
> >>things happen and my int / long fields are not set. This is shown
> >>in the
> >>following example:
> >>
> >>Post:
> >>{"int1":1,"string1":"string","strings":["s1","s2"],"int2":2,"long1":
> >>3}
> >>Response:
> >>{"int1":1,"int2":0,"long1":0,"string1":"string","strings":
> >>["s1","s2"]}
> >>equals(): false
> >>[...fields int2 and long1 are not being set.]
> >>----------
> >>
> >>I've created a test script which constructs various JSON strings
> >>and posts
> >>them off to my takeTest() method, which returns a JSON
> >>representation of the
> >>parsed Test object.
> >>I then use Jackson within my test script to build this into a new
> >>Test
> >>object (via a JaxbAnnotationIntrospector) and test equality on the
> >>two
> >>objects.
> >>
> >>Post:
> >>{"string1":"string","strings":["s1","s2"],"int1":1,"int2":2,"long1":
> >>3}
> >>Response:
> >>{"int1":0,"int2":0,"long1":0,"string1":"string","strings":
> >>["s1","s2"]}
> >>equals(): false
> >>[... none of the int or long fields are being set]
> >>----------
> >>
> >>Post:
> >>{"int1":1,"int2":2,"string1":"string","strings":["s1","s2"],"long1":
> >>3}
> >>Response:
> >>{"int1":1,"int2":2,"long1":0,"string1":"string","strings":
> >>["s1","s2"]}
> >>equals(): false
> >>[... int1 and int2 are correctly set, but long1 is not set]
> >>----------
> >>
> >>Post:
> >>{"int1":1,"int2":2,"long1":3,"string1":"string","strings":
> >>["s1","s2"]}
> >>Response:
> >>{"int1":1,"int2":2,"long1":3,"string1":"string","strings":
> >>["s1","s2"]}
> >>equals(): true
> >>----------
> >>
> >>If I attach an @XmlType(propOrder = { "int1", "int2", "long1",
> >>"string1",
> >>"strings" }) annotation to my Test class, Jackson will happily
> >>follow this
> >>and generate JSON that matches JAXB's expected ordering. I don't
> >>however
> >>think the onus should be on clients to guarantee the 'primitives
> >>first'
> >>ordering that Jersey / JAXB seems to expect.
> >>
> >>My issue here is that if I'm using a particular JSON library (in
> >>whatever
> >>language, divorced from my server) to post JSON at /test/post/ I
> >>cannot
> >>guarantee element ordering. Is this a bug with Jersey's use of
> >>JAXB? Or
> >>potentially JAXB by itself?
> >
> >--
> >http://blogs.sun.com/japod
> >
> >---------------------------------------------------------------------
> >To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> >For additional commands, e-mail: users-help_at_jersey.dev.java.net
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>
--
http://blogs.sun.com/japod