-
Enhancement
-
Resolution: Won't Do
-
Minor
-
2.3.2.Final
I am encountering an error while demarshalling a JSON object as input to a JAX-RS method. After some tinkering, the error seems to be due to the XmlNsMap defined for the output not being applied to the input.
org.jboss.resteasy.plugins.providers.jaxb.JAXBUnmarshalException: javax.xml.bind.UnmarshalException - with linked exception: [com.sun.istack.SAXParseException2; columnNumber: 0; unexpected element (uri:"", local:"ejava.link"). Expected elements are <{http://ejava.info}link>]
Is there something similar to the ContextResolver<JAXBContext> that has to be done for JSON XmlNsMaps?
The RESTEasy JSON examples generate data (which I can do) but none consume data. I have gotten it to work by injecting a String and demarshalling the object thru the Jettison APIs. I can also get the
manual approach to generate the same error message – which leads me to think the input/demarshaller for JSON needs more than the @Mapped annotation.
- I am working with a simple Link class in the "http://ejava.info" namespace.
package ejava.util.rest; @XmlRootElement(name="link", namespace="http://ejava.info") @XmlType(name="LinkType", namespace="http://ejava.info") public class Link { ... }
- I have attempted to pass the JSON object straight into the method and have RESTEasy do the demarshalling. I have added the @Mapped/@XmlNsMap annotations for the used namespace. This has allowed
me to generate Link objects successfully.@PUT @Path("attributes") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Mapped(namespaceMap = { @XmlNsMap(namespace = "http://ejava.info", jsonName = "ejava"), }) public Response putLinkJSON(Link link) //String jsonString) throws JSONException, XMLStreamException, JAXBException { link.setHref(uriInfo.getRequestUri()); link.setType(MediaType.APPLICATION_XML); return Response.ok(link, MediaType.APPLICATION_JSON).build(); }
- When I PUT my JSON object to the method...
PUT /jaxrs-representations-dmv-war6/data/attributes HTTP/1.1 Content-Type: application/json Accept: application/json Content-Length: 30 Host: dmv.ejava.info:9092 Connection: Keep-Alive User-Agent: Apache-HttpClient/4.1.3 (java 1.5) {"ejava.link":{"@rel":"self"}}
... it reports the following error
-Failed executing PUT /data/attributes org.jboss.resteasy.plugins.providers.jaxb.JAXBUnmarshalException: javax.xml.bind.UnmarshalException - with linked exception: [com.sun.istack.SAXParseException2; columnNumber: 0; unexpected element (uri:"", local:"ejava.link"). Expected elements are <{http://ejava.info}link>] at org.jboss.resteasy.plugins.providers.jaxb.AbstractJAXBProvider.readFrom(AbstractJAXBProvider.java:125)
- When I inject the JSON object into a String and manually demarshal the JSON. It works (see the 200 reply below)
@PUT @Path("attributes") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Mapped(namespaceMap = { @XmlNsMap(namespace = "http://ejava.info", jsonName = "ejava"), }) public Response putLinkJSON(String jsonString) throws JSONException, XMLStreamException, JAXBException { JAXBContext ctx = JAXBContext.newInstance(Link.class); Configuration config = new Configuration(); Map<String, String> xmlToJsonNamespaces = new HashMap<String,String>(); xmlToJsonNamespaces.put("http://ejava.info", "ejava"); config.setXmlToJsonNamespaces(xmlToJsonNamespaces); MappedNamespaceConvention con = new MappedNamespaceConvention(config); JSONObject obj = new JSONObject(jsonString); XMLStreamReader xmlStreamReader = new MappedXMLStreamReader(obj, con); Unmarshaller unmarshaller = ctx.createUnmarshaller(); Link link = (Link) unmarshaller.unmarshal(xmlStreamReader); link.setHref(uriInfo.getRequestUri()); link.setType(MediaType.APPLICATION_XML); return Response.ok(link, MediaType.APPLICATION_JSON).build(); }
HTTP/1.1 200 OK Content-Type: application/json Transfer-Encoding: chunked Server: Jetty(6.1.26) {"ejava.link":{"@href":"http:\/\/dmv.ejava.info:9092\/jaxrs-representations-dmv-war6\/data\/attributes","@rel":"self","@type":"application\/xml"}}
- When I comment out the Map in the working code...
Map<String, String> xmlToJsonNamespaces = new HashMap<String,String>(); //xmlToJsonNamespaces.put("http://ejava.info", "ejava"); config.setXmlToJsonNamespaces(xmlToJsonNamespaces);
...I get an error message similar to the one from the original case.
[com.sun.istack.SAXParseException2; columnNumber: 0; unexpected element (uri:"", local:"ejava.link"). Expected elements are <{http://ejava.info}link>] at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:434) at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:371) at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:341) at ejava.examples.jaxrsrep.handlers.JSONHandlerDemoRS.putLinkJSON(JSONHandlerDemoRS.java:100)
This leads me to think that I need to register something similar to the ContextResolver that I have done for other JAXB cases – however, I haven't located any documentation on how I can help setup the
Jettison demarshaller.