【问题标题】:How to POST JSON request to a Jersey REST service?如何将 JSON 请求发布到 Jersey REST 服务?
【发布时间】:2012-04-01 03:25:54
【问题描述】:

我可以成功地将 XML 数据发布到我的服务,但是尝试使用 JSON 做同样的事情失败了。 POJO 是:

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

服务资源是:

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

我正在做如下的 POST:

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

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

服务器正在响应 400 错误请求。我搜索了互联网,但没有找到发布 JSON 的好例子。任何帮助表示赞赏。谢谢。

【问题讨论】:

    标签: jersey eclipselink jax-rs moxy


    【解决方案1】:

    WLS 发行版中捆绑的 EclipseLink 模块(Eclipse Persistence Services - 2.3.2.v20111125-r10461)似乎存在问题:

    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
    

    作为一种解决方法,您可以在 JAXB 类(例如地址)所在的包中创建一个 jaxb.properties 文件,其中包含以下内容:

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

    这应该告诉 WLS 使用来自 JAXB RI(也存在于 WLS 12c 中)的 JAXBContext 类的实例,而不是来自 EclipseLink 的实例。请记住,这只是一种解决方法。

    【讨论】:

    • 这真的会导致 400 错误请求(而不是 500 服务器错误)还是这是一个不同的问题?我看到您建议标记问题 EclipseLink。
    • 这仍然是同一个问题 - 上面的异常导致 Jersey 出现 400 Bad Request。
    • 实际上,使用 JAXB 伪造 XML 事件以读取 JSON 的 Jersey Json xml 阅读器似乎存在一些问题(请参阅最后的堆栈跟踪)。 IE。问题可能出在 Jersey 的 JsonXmlStreamReader 而不是 MOXy。
    • 这里是 Jersey JsonXmlStreamReader 问题的链接:java.net/jira/browse/JERSEY-1042
    【解决方案2】:

    @Consumes("application/json") 注释添加到您的fix() 方法中。

    更新:这对我有用:

    资源方法:

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

    地址类:

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

    这是我发送的请求:

    Accept  application/json
    Content-Type    application/json; charset=UTF-8
    
    {"city":"Miami","zip":"33130"}
    

    这是我得到的回应:

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

    【讨论】:

    • 这没有帮助。我什至添加了一个 Accept 标头:Accept: application/json, text/javascript, /; q=0.01
    • 这很奇怪,它对我有用。我已经用我的实现方式更新了我的答案。
    • 检查服务器日志,看看服务器端是否有任何堆栈跟踪。
    • 嗨 Martin,基本上,WebLogic 12c 附带的 Jersey 版本似乎存在缺陷。我无法进行表单 POST 并返回 JSON。只有 GET 可以返回 JSON。该缺陷似乎与 POST 方法有关。
    • 我不知道该说什么。你的建议应该有效。有时间我会用 Tomcat/Jersey 进行验证。现在,在 WebLogic 中,我做了一个解决方法并发送带有 URL 参数的 GET 请求。
    猜你喜欢
    • 2013-01-15
    • 2016-03-25
    • 2015-12-17
    • 1970-01-01
    • 2016-12-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    相关资源
    最近更新 更多