Uploaded image for project: 'RESTEasy'
  1. RESTEasy
  2. RESTEASY-706

Error with JSON method input/demarshalling

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Won't Do
    • Icon: Minor Minor
    • 2.3.4.Final
    • 2.3.2.Final
    • jaxrs

      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.

              patriot1burke@gmail.com Bill Burke (Inactive)
              jcstaff_jira jim stafford (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated:
                Resolved: