在Osgi中使用Jersey在REST服务中使用application / json

时间:2013-09-06 14:45:05

标签: json rest jaxb jersey osgi

我正在使用Jersey在Osgi包中部署一些REST服务。服务标记为

@POST
@Path("/adduser")
@Consumes(MediaType.APPLICATION_XML+","+MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_XML)
public Message addUser(User user) {
 ...
}

我遇到的第一个问题是该服务不接受我放入@Consumes符号的两种MIME类型,而只接受第一种。

第二个也是最差的是当我尝试调用服务时收到以下异常。我可以@Consumes text / plain,我可以@Produces application / xml例如但是如果我尝试@Consumes应用程序/ json或application / xml服务器抛出异常。

当我使用REST客户端或ajax调用使用格式良好的json或xml进行调用时抛出异常,如果服务只是接收text / plain或者没有收到任何对xml进行正确响应的客户端的响应,那么当我发送POJO但没有收到它们时,序列化器工作正常。

 javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.lang.LinkageError: loader constraint violation: when resolving interface method "javax.xml.bind.Unmarshaller.unmarshal(Ljavax/xml/transform/Source;)Ljava/lang/Object;" the class loader (instance of org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader) of the current class, org/glassfish/jersey/message/internal/XmlRootElementJaxbProvider, and the class loader (instance of <bootloader>) for resolved class, javax/xml/bind/Unmarshaller, have different Class objects for the type ject; used in the signature
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:353)
    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.felix.http.base.internal.handler.ServletHandler.doHandle(ServletHandler.java:96)
    at org.apache.felix.http.base.internal.handler.ServletHandler.handle(ServletHandler.java:79)
    at org.apache.felix.http.base.internal.dispatch.ServletPipeline.handle(ServletPipeline.java:42)
    at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:49)
    at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:33)
    at es.upm.cedint.gateway.api.corssupport.CORSFilter.doFilter(CORSFilter.java:164)
    at es.upm.cedint.gateway.api.corssupport.CORSFilter.doFilter(CORSFilter.java:246)
    at org.apache.felix.http.base.internal.handler.FilterHandler.doHandle(FilterHandler.java:88)
    at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:76)
    at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:47)
    at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:33)
    at es.upm.cedint.gateway.api.security.SecurityFilter.doFilter(SecurityFilter.java:87)
    at org.apache.felix.http.base.internal.handler.FilterHandler.doHandle(FilterHandler.java:88)
    at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:76)
    at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:47)
    at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:33)
    at org.apache.felix.http.base.internal.dispatch.FilterPipeline.dispatch(FilterPipeline.java:48)
    at org.apache.felix.http.base.internal.dispatch.Dispatcher.dispatch(Dispatcher.java:39)
    at org.apache.felix.http.base.internal.DispatcherServlet.service(DispatcherServlet.java:67)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:390)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:326)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
    at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:943)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
    at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

Caused by: org.glassfish.jersey.server.ContainerException: java.lang.LinkageError: loader constraint violation: when resolving interface method "javax.xml.bind.Unmarshaller.unmarshal(Ljavax/xml/transform/Source;)Ljava/lang/Object;" the class loader (instance of org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader) of the current class, org/glassfish/jersey/message/internal/XmlRootElementJaxbProvider, and the class loader (instance of <bootloader>) for resolved class, javax/xml/bind/Unmarshaller, have different Class objects for the type ject; used in the signature
    at org.glassfish.jersey.servlet.internal.ResponseWriter.rethrow(ResponseWriter.java:230)
    at org.glassfish.jersey.servlet.internal.ResponseWriter.failure(ResponseWriter.java:212)
    at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:401)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:243)
    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:322)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:211)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:979)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:344)
    ... 36 more

Caused by: java.lang.LinkageError: loader constraint violation: when resolving interface method "javax.xml.bind.Unmarshaller.unmarshal(Ljavax/xml/transform/Source;)Ljava/lang/Object;" the class loader (instance of org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader) of the current class, org/glassfish/jersey/message/internal/XmlRootElementJaxbProvider, and the class loader (instance of <bootloader>) for resolved class, javax/xml/bind/Unmarshaller, have different Class objects for the type ject; used in the signature
        at org.glassfish.jersey.message.internal.XmlRootElementJaxbProvider.readFrom(XmlRootElementJaxbProvider.java:140)
        at org.glassfish.jersey.message.internal.AbstractRootElementJaxbProvider.readFrom(AbstractRootElementJaxbProvider.java:122)
        at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:181)
        at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:134)
        at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundReadFrom(MappableExceptionWrapperInterceptor.java:72)
        at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:134)
        at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:988)
        at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:833)
        at org.glassfish.jersey.server.ContainerRequest.readEntity(ContainerRequest.java:252)
        at org.glassfish.jersey.server.internal.inject.EntityParamValueFactoryProvider$EntityValueFactory.get(EntityParamValueFactoryProvider.java:96)
        at org.glassfish.jersey.server.internal.inject.AbstractHttpContextValueFactory.provide(AbstractHttpContextValueFactory.java:66)
        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:94)
        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:237)
        ... 45 more

任何人都知道可能出现什么问题?

PD:我想在序列化的User类的开头有@XMLRootElement,我使用的服务器是Jetty。

1 个答案:

答案 0 :(得分:1)

对于第一个问题,我认为您不应该有一个具有两个不同签名的功能。我的意思是,如果你想接受json或XML,那么它们是两个不同的函数,尽管从java的角度来看它们看起来是一样的。在你的情况下,我将创建这三个函数:

@POST
@Path("/adduser")
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
public Message addUserXML(User user) {
 return addUserInternal(user);
}

@POST
@Path("/adduser")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_XML)
public Message addUserJSon(User user) {
 return addUserInternal(user);
}

private Message addUserInternal(User user) {
  ...
}

第二个问题:Java 6(在我看来)发生的最糟糕的事情之一是他们将JAXB和其他技术转移到JRE类路径中。我想你的一个捆绑包中也有JAXB。 Jersey和包含REST API的bundle连接到不同的包。其中一个连接到包含JAXB的bundle,而另一个连接到引导类路径(来自JDK的包)

你可以有两个解决方案(至少)

第一个解决方案

通过配置OSGi环境,从引导类路径中排除JAXB包。

第二个解决方案

来自JDK的软件包的版本为0.0.0_jdkversion。来自捆绑包的JAXB包具有更好的更高版本,如2.1.1。您可以编辑Jersey的MANIFEST.MF和您的包以指向该版本的包。