0

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

@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 或应用程序/xml,服务器会抛出异常。

当我使用 REST 客户端或 ajax 调用使用格式正确的 json 或 xml 进行调用时抛出异常,如果服务只接收文本/纯文本或未接收到任何内容,则对客户端的响应在 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。

4

1 回答 1

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 的捆绑包连接到不同的包。其中一个连接到包含 JAXB 的包,而另一个连接到引导类路径(来自 JDK 的包)

您可以有两种解决方案(至少)

第一个解决方案

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

第二种解决方案

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

于 2013-09-06T15:50:07.557 回答