5

I can successfully post XML data to my service, but, trying to do the same using JSON is failing. The POJO is:

@XmlRootElement
public class Address {
    String city;
    String zip;
    //Getters & setters...
}

The service resource is:

@POST
@Produces("application/json")
public Address fix(Address a) {
    return a;
}

I am doing a POST as follows:

POST /AcmeWeb/svc/simple HTTP/1.1
Content-Length: 30
Content-Type: application/json; charset=UTF-8

{"city":"Miami","zip":"33130"}

The server is responding with a 400 Bad Request. I scoured the Internet but found no good example of posting JSON. Any help is appreciated. Thanks.

bdoughan
  • 147,609
  • 23
  • 300
  • 400
RajV
  • 6,860
  • 8
  • 44
  • 62

2 Answers2

4

Add @Consumes("application/json") annotation to your fix() method.

Update: This works for me:

Resource method:

@POST
@Produces("application/json")
@Consumes("application/json")
public Address post(Address addr) {
    return addr;
}

Address class:

@XmlRootElement
public class Address {
    public String city;
    public String zip;
}

This is the request I am sending:

Accept  application/json
Content-Type    application/json; charset=UTF-8

{"city":"Miami","zip":"33130"}

This is what I get as a response:

{"city":"Miami","zip":"33130"}
Martin Matula
  • 7,969
  • 1
  • 31
  • 35
  • That didn't help. I even added an Accept header: Accept: application/json, text/javascript, */*; q=0.01 – RajV Mar 15 '12 at 17:43
  • That's weird, it works for me. I've updated my answer with how I implemented it. – Martin Matula Mar 15 '12 at 18:44
  • Check the server log to see if there is any stack trace on the server side. – Martin Matula Mar 15 '12 at 18:52
  • Hi Martin, Basically, there seems to be a defect in the version of Jersey that comes with WebLogic 12c. I can't event do a form POST and get JSON back. Only a GET can return JSON. The defect seems to be related to the POST method. – RajV Mar 15 '12 at 19:15
  • I don't know what to say. What you've suggested should work. I will verify with Tomcat/Jersey when I have some time. For now, in WebLogic, I did a work around and sending a GET request with URL parameters. – RajV Mar 15 '12 at 19:26
  • Which version of WebLogic? Are you using the Jersey shared library that ships with it, or are you using 12c which has Jersey on class path? Or some older version and bundling Jersey in your war? In that case, what Jersey jars are you packaging with your app? And is your app using the default class path scanning for resources? Or package scanning? – Martin Matula Mar 15 '12 at 20:26
  • I'm using WebLogic 12c and the Jersey that comes with it (v1.9?). – RajV Mar 16 '12 at 12:52
1

There seems to be a problem with the EclipseLink module (Eclipse Persistence Services - 2.3.2.v20111125-r10461) bundled in the WLS distribution:

javax.ws.rs.WebApplicationException: javax.xml.bind.UnmarshalException
 - with linked exception:
[Exception [EclipseLink-25004] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred unmarshalling the document
Internal Exception: java.util.NoSuchElementException]
    at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:113)
    at com.sun.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:474)
    at com.sun.jersey.server.impl.model.method.dispatch.EntityParamDispatchProvider$EntityInjectable.getValue(EntityParamDispatchProvider.java:123)
    at com.sun.jersey.server.impl.inject.InjectableValuesProvider.getInjectableValues(InjectableValuesProvider.java:46)
    at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$EntityParamInInvoker.getParams(AbstractResourceMethodDispatchProvider.java:153)
    at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$TypeOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:183)
    at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75)
    at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:288)
    at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108)
    at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
    at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84)
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1469)
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1400)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1349)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1339)
    at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:699)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:844)
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:242)
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:216)
    at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:132)
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:352)
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:235)
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3284)
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3254)
    at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
    at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
    at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:57)
    at weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2163)
    at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2089)
    at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2074)
    at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1512)
    at weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:254)
    at weblogic.work.ExecuteThread.execute(ExecuteThread.java:256)
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:221)
Caused by: javax.xml.bind.UnmarshalException
 - with linked exception:
[Exception [EclipseLink-25004] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred unmarshalling the document
Internal Exception: java.util.NoSuchElementException]
    at org.eclipse.persistence.jaxb.JAXBUnmarshaller.handleXMLMarshalException(JAXBUnmarshaller.java:827)
    at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:407)
    at com.sun.jersey.json.impl.BaseJSONUnmarshaller.unmarshalJAXBElementFromJSON(BaseJSONUnmarshaller.java:108)
    at com.sun.jersey.json.impl.BaseJSONUnmarshaller.unmarshalFromJSON(BaseJSONUnmarshaller.java:97)
    at com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider.readFrom(JSONRootElementProvider.java:125)
    at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:111)
    ... 35 more
Caused by: Exception [EclipseLink-25004] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred unmarshalling the document
Internal Exception: java.util.NoSuchElementException
    at org.eclipse.persistence.exceptions.XMLMarshalException.unmarshalException(XMLMarshalException.java:95)
    at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.convertSAXException(SAXUnmarshaller.java:842)
    at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:830)
    at org.eclipse.persistence.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:602)
    at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:399)
    ... 39 more
Caused by: java.util.NoSuchElementException
    at com.sun.jersey.json.impl.reader.JsonReaderXmlEvent.getAttributeValue(JsonReaderXmlEvent.java:147)
    at com.sun.jersey.json.impl.reader.JsonXmlStreamReader.getAttributeValue(JsonXmlStreamReader.java:655)
    at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader$IndexedAttributeList.getValue(XMLStreamReaderReader.java:312)
    at org.eclipse.persistence.oxm.record.UnmarshalRecord.startElement(UnmarshalRecord.java:648)
    at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parseEvent(XMLStreamReaderReader.java:108)
    at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parse(XMLStreamReaderReader.java:81)
    at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parse(XMLStreamReaderReader.java:71)
    at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:818)
    ... 41 more

As a workaround you can create a jaxb.properties file in the package where your JAXB classes (e.g. Address) are located with the following contents:

javax.xml.bind.context.factory=com.sun.xml.bind.v2.ContextFactory

This should tell the WLS to use an instance of the JAXBContext class from JAXB RI (which is also present in WLS 12c) instead of the one from EclipseLink. Keep in mind this is just a workaround.

Michal Gajdos
  • 10,339
  • 2
  • 43
  • 42
  • Is that really going to cause a 400 Bad Request (as opposed to a 500 Server Error) or is this a different issue? I see you've proposed tagging the question EclipseLink. – Rup Mar 20 '12 at 13:28
  • This is still the same issue - the exception above is causing a 400 Bad Request in Jersey. – Michal Gajdos Mar 20 '12 at 14:29
  • 1
    Actually, looks like Jersey Json xml reader that fakes XML events to read JSON using JAXB has some issue (see the last stack trace). I.e. the issue may be with Jersey's JsonXmlStreamReader rather than MOXy. – Martin Matula Mar 20 '12 at 15:23
  • 1
    Here is a link to the Jersey JsonXmlStreamReader issue: http://java.net/jira/browse/JERSEY-1042 – bdoughan Sep 11 '12 at 17:52