users@jersey.java.net

Re: [Jersey] JSON Unmarshalling Issue

From: Ni Yue <ni2yue4_at_gmail.com>
Date: Wed, 3 Jun 2009 10:59:11 +0800

Hi Jakub,

I filed a feature request for that:
https://jersey.dev.java.net/issues/show_bug.cgi?id=301

And for badgerFish notation, I changed my test to use badgerFish notation,
but still can not get it to work.
I got a JSON response (in the browser):

{"fruits":{"@xmlns":{"ns2":"http:\/\/fruits.example.org","$":"http:\/\/
> fruitbase.example.org"},"fruit":{"@xmlns":{"xsi":"http:\/\/www.w3.org
> \/2001\/XMLSchema-instance"},"@xsi:type":"ns2:Apple","name":{"$":"apple"},"color":{"$":"red"},"ns2:weight":{"$":"2"}}}}
>

Although "ns2" is specified as a prefix for namespace "
http://fruits.example.org" in response, but it still failed to be
unmarshalled in client side with the error message:

> javax.ws.rs.WebApplicationException: javax.xml.bind.UnmarshalException
> - with linked exception:
> [javax.xml.stream.XMLStreamException: Invalid prefix ns2 on element
> ns2:weight]


Do you have any idea what's the problem here? You can change my
JAXBContextResolver in attached maven project to use badgerFish notation to
reproduce this issue. Thanks.

Here's the full stack trace printed in the client side:
javax.ws.rs.WebApplicationException: javax.xml.bind.UnmarshalException
 - with linked exception:
[javax.xml.stream.XMLStreamException: Invalid prefix ns2 on element
ns2:weight]
    at
com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:99)
    at
com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:259)
    at
com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:220)
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:561)
    at com.sun.jersey.api.client.WebResource.get(WebResource.java:179)
    at org.example.JsonTest.testJsonResponse(JsonTest.java:16)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at junit.framework.TestCase.runTest(TestCase.java:164)
    at junit.framework.TestCase.runBare(TestCase.java:130)
    at junit.framework.TestResult$1.protect(TestResult.java:106)
    at junit.framework.TestResult.runProtected(TestResult.java:124)
    at junit.framework.TestResult.run(TestResult.java:109)
    at junit.framework.TestCase.run(TestCase.java:120)
    at junit.framework.TestSuite.runTest(TestSuite.java:230)
    at junit.framework.TestSuite.run(TestSuite.java:225)
    at
org.junit.internal.runners.OldTestClassRunner.run(OldTestClassRunner.java:76)
    at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
    at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
    at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: javax.xml.bind.UnmarshalException
 - with linked exception:
[javax.xml.stream.XMLStreamException: Invalid prefix ns2 on element
ns2:weight]
    at
com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:426)
    at
com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:362)
    at
com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:339)
    at
com.sun.jersey.json.impl.JSONUnmarshaller.unmarshal(JSONUnmarshaller.java:100)
    at
com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider.readFrom(JSONRootElementProvider.java:105)
    at
com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:97)
    ... 24 more
Caused by: javax.xml.stream.XMLStreamException: Invalid prefix ns2 on
element ns2:weight
    at
org.codehaus.jettison.badgerfish.BadgerFishConvention.createQName(BadgerFishConvention.java:76)
    at org.codehaus.jettison.Node.<init>(Node.java:55)
    at
org.codehaus.jettison.badgerfish.BadgerFishXMLStreamReader.processKey(BadgerFishXMLStreamReader.java:100)
    at
org.codehaus.jettison.badgerfish.BadgerFishXMLStreamReader.processElement(BadgerFishXMLStreamReader.java:87)
    at
org.codehaus.jettison.badgerfish.BadgerFishXMLStreamReader.next(BadgerFishXMLStreamReader.java:67)
    at
com.sun.xml.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(StAXStreamConnector.java:192)
    at
com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:360)
    ... 28 more

Regards,
Ni Yue

2009/6/2 Jakub Podlesak <Jakub.Podlesak_at_sun.com>

> Hi Ni,
>
>
> Ni Yue wrote:
>
>> Hello,
>>
>> I am using Jersey to serve JSON response and met some issue. In my case, I
>> used JAXB for XML marshalling and used Jersey's build-in function to map XML
>> to JSON. And there're multiple namespaces in my XML schema, for example:
>> *
>> base.xsd:*
>>
>> <?xml version="1.0" encoding="UTF-8"?>
>> <schema
>> xmlns="http://www.w3.org/2001/XMLSchema"
>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>> xmlns:base="http://fruitbase.example.org"
>> targetNamespace="http://fruitbase.example.org"
>> elementFormDefault="qualified">
>> <element name="fruits">
>> <complexType>
>> <sequence>
>> <element name="fruit" type="base:Fruit"
>> minOccurs="0"></element>
>> </sequence>
>> </complexType>
>> </element>
>> <complexType name="Fruit">
>> <sequence>
>> <element name="name" type="string"/>
>> <element name="color" type="string"/>
>> </sequence>
>> </complexType>
>> </schema>
>>
>>
>> *fruits.xsd:*
>>
>> <?xml version="1.0" encoding="UTF-8"?>
>> <schema
>> xmlns="http://www.w3.org/2001/XMLSchema"
>> xmlns:base="http://fruitbase.example.org"
>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>> xmlns:fruits="http://fruits.example.org"
>> targetNamespace="http://fruits.example.org"
>> elementFormDefault="qualified">
>> <import namespace="http://fruitbase.example.org"
>> schemaLocation="base.xsd"></import>
>> <complexType name="Apple">
>> <complexContent>
>> <extension base="base:Fruit">
>> <sequence>
>> <element name="weight" type="int"></element>
>> </sequence>
>> <anyAttribute/>
>> </extension>
>> </complexContent>
>> </complexType>
>> <complexType name="Orange">
>> <complexContent>
>> <extension base="base:Fruit">
>> </extension>
>> </complexContent>
>> </complexType>
>> </schema>
>>
>>
>> My question is:
>> 1) In order to correctly marshall/unmarshall JSON request/response using
>> Jersey and its client API, which JSON notation (mapped, mappedJettison,
>> badgerFish, natual) should I use in this case (with multiple namespaces in
>> schema)? It seems only mappedJettison notation can be used as I did a simple
>> search in the mail list archive, but I am not sure.
>>
>
> It should be supported for both Jettison based notations (Jettison mapped
> and BadgerFish),
> where for the Badgerfish, the thing (namespace handling) should work out of
> the box, without a need of any special
> configuration, while when using the Jettison mapped notation, you would
> need to explicitly
> configure the namespace mapping (see
> https://jersey.dev.java.net/documentation/1.1.0-ea/user-guide.html#d4e603for details)
>
>
>> 2) I implemented a JAXBContextResolver and tried mappedJettison notation:
>>
>> public JAXBContextResolver() throws Exception {
>> Map<String, String> namespaceMap = new HashMap<String,
>> String>();
>> namespaceMap.put("http://www.w3.org/2001/XMLSchema", "xs");
>> namespaceMap.put("http://www.w3.org/2001/XMLSchema-instance",
>> "xsi");
>> namespaceMap.put("http://fruitbase.example.org", "base");
>> namespaceMap.put("http://fruits.example.org", "fruits");
>> JSONConfiguration config =
>> JSONConfiguration.mappedJettison().xml2JsonNs(namespaceMap).build();
>> this.m_context = new JSONJAXBContext(
>> config,
>> m_types);
>> }
>>
>> But in the JSON response, I found JAXB used a random prefix (ns2) for
>> QName in attribute values:
>>
>> {"base.fruits":{"base.fruit":{"@xsi.type":"*ns2:Apple*","base.name <
>> http://base.name>":"apple","base.color":"red","fruits.weight":2}}}
>>
>> Is it a bug for Jersey? I know it is possible to change that behavior via
>> JAXB API (https://jaxb.dev.java.net/guide/Changing_prefixes.html), but it
>> is wrapped by Jersey, and how can I control that in Jersey?
>>
>
> You would need to implement a JAXB NamespacePrefixMapper (see
> http://blogs.sun.com/enterprisetechtips/resource/JAXBSample.java) and hand
> it over to the actual Marshaller.
> It is now not possible to do so out-of-the-box right now, but it is a great
> idea to have such a feature in place.
> Could you please file a feature request, so that i can work on this at the
> after JavaOne timeframe?
>
> Thanks,
>
> ~Jakub
>
>>
>> I attached a zipped maven project, which contains detailed implementation
>> and test case for my issue. Thanks in advance for all your help.
>>
>> Environment:
>> Jersey 1.0.3
>> Java 1.5
>>
>> Regards,
>> Ni Yue
>>
>> ------------------------------------------------------------------------
>>
>> ---------------------------------------------------------------------
>> 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
>
>