在Jersey 2.3中使用JSON会抛出XML异常

时间:2013-10-11 15:14:08

标签: json jersey entity moxy

我正在尝试使用自定义对象制作Jersey 2.3 + Moxy。当我从这些对象生成JSON时,一切都很好,但是当我想通过POST使用它们时拒绝工作。代码优先:

自定义对象:

@XmlRootElement
public class ContentAction extends Action {

    private String contentType;
    private Integer contentLength;

    public ContentAction() {
        setType(ActionType.CONTENT);
    }

    public String getContentType() {
        return contentType;
    }

    public void setContentType(String contentType) {
        this.contentType = contentType;
    }

    public Integer getContentLength() {
        return contentLength;
    }

    public void setContentLength(Integer contentLength) {
        this.contentLength = contentLength;
    }
}

资源片段(路径在类上声明):

@POST
@Produces(JsonHelper.JSON_UTF8)
public Action saveAction(@QueryParam("action") ContentAction action) throws IOException {
    ActionEntity entity = actionConverter.toEntity(action);
    entity.setBeacon(beaconService.findById(action.getBeacon().getId()));

    return actionConverter.convert(actionService.save(entity));
}

API调用者(负责发送请求的类):

URI uri = buildUri(path, params);

HttpPost httpPost = new HttpPost(uri);
httpClient.execute(httpPost);

buildUri只是从地址&创建URI。参数 该操作将转换为JSON,如下所示:mapper.writeValueAsString(action)

例外:

org.glassfish.jersey.server.internal.inject.ExtractorException: Error unmarshalling JAXB object of type "class com.kontakt.platform.apicommon.model.ContentAction".
    at org.glassfish.jersey.server.internal.inject.JaxbStringReaderProvider$RootElementProvider$1.fromString(JaxbStringReaderProvider.java:195)
    at org.glassfish.jersey.server.internal.inject.AbstractParamValueExtractor.convert(AbstractParamValueExtractor.java:138)
    at org.glassfish.jersey.server.internal.inject.AbstractParamValueExtractor.fromString(AbstractParamValueExtractor.java:129)
    at org.glassfish.jersey.server.internal.inject.SingleValueExtractor.extract(SingleValueExtractor.java:83)
    at org.glassfish.jersey.server.internal.inject.QueryParamValueFactoryProvider$QueryParamValueFactory.provide(QueryParamValueFactoryProvider.java:88)
    at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:81)
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:121)
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:195)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:353)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:343)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:255)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:318)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:235)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:983)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:359)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1008)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1852)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:722)
Caused by: javax.xml.bind.UnmarshalException
 - with linked exception:
[org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.]
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:335)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:512)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:209)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:175)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:140)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:123)
    at org.glassfish.jersey.server.internal.inject.JaxbStringReaderProvider$RootElementProvider$1.fromString(JaxbStringReaderProvider.java:190)
    ... 40 more
Caused by: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:177)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:441)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:368)
    at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1388)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:998)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:607)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:116)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:489)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:835)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1210)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:203)
    ... 44 more

当我删除@XmlRootElement时,Jersey尝试使用字符串参数从构造函数创建对象(如果已添加)=没有自动创建bean。

我已经坚持了两天,我会非常感激你的帮助。

3 个答案:

答案 0 :(得分:0)

我认为问题是您需要设置内容类型。由于您没有指定内容类型,因此jersey假设它正在重新获取xml,但它实际上是json。错误消息来自jaxb尝试读取xml标头并查找无效字符。尝试使用泽西客户端而不是http帖子。另外我认为你可能会改变你的@Produces(MediaType.APPLICATION_JSON)以保持一致性。

@Produces(MediaType.APPLICATION_JSON)

POST代码示例

最重要的部分是我正在设置我要发布的类型(MediaType.Application_JSON)。

WebResource webResource = createRestClient(true).resource(
             REST_BASE_PATH + "/service");

ClientResponse response = webResource.type(MediaType.APPLICATION_JSON)
            .accept(MediaType.APPLICATION_JSON)
            .post(ClientResponse.class, contentActionObject);

Assert.assertTrue(response.getStatus() == 200);

如果确实需要使用HttpPost对象,那么应该有一个配置选项来设置http标头。我使用HttpUrlConnection完成了这个。您必须将内容类型设置为application / json而不是xml。

HttpURLConnection connection = null;
connection = (HttpURLConnection) new URL(requestUrl).openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/xml");
connection.setRequestProperty("Content-Type", "application/xml");

答案 1 :(得分:0)

对于符合以下模式的媒体类型,

EclipseLink MOXy将被Jersey选为JSON绑定提供者。

  • * / json(即application / json和text / json)
  • / + JSON

根据您的例外情况,似乎媒体类型已用JsonHelper.JSON_UTF8表示与此模式不匹配。

答案 2 :(得分:0)

我知道这有点老了,但我使用Jersey 2.3 + Moxy遇到了基本相同的问题。相同的情况和相同的异常正在发生。唯一的区别是我的POST方法注释为:

@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)

我确实发现,当我在请求正文中传递相同的JSON表示而不是作为查询参数时,它已成功解组。这需要将POST方法声明更改为:

public Action saveAction(ContentAction action)

不确定这是否适合您。如果你找到了解决方案,我会有兴趣听听它是什么。