繁体   English   中英

OSGi应用程序内的REST客户端

[英]REST client inside of OSGi application

我需要将REST客户端集成到使用Apache Felix实现的现有OSGi应用程序中。 REST服务基于JAX-RS的RESTeasy实现(版本2.3.2.Final)。 我创建了一个单独的包,其中包含客户端的依赖项,导出所需的RESTeasy包并将其导入到使用客户端的包中,但遗憾的是我无法在OSGi上下文中使用它。

我尝试了两种不同的方法。 第一个使用通用ClientRequest:

ClientRequest request = new ClientRequest(MyService.URL_TEST+"/stats");
request.body(javax.ws.rs.core.MediaType.APPLICATION_XML, stats);
ClientResponse<String> response = request.post(String.class);

我在这种情况下得到的错误非常奇怪:

[java] java.lang.RuntimeException: java.lang.ClassCastException:
org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor cannot be cast to 
org.jboss.resteasy.client.ClientExecutor

我知道ApacheHttpClient4Executor实现了ClientExecutor接口。

当我尝试在RESTeasy周围使用我自己的REST客户端包装时,如下所示:

MyService myService = MyServiceClient.getInstance();
myService.saveStatistics(stats);

我得到一个不同的例外:

[java] java.lang.LinkageError: ClassCastException: attempting to
castjar:file:/D:/Development/Eclipses/eclipse_4.2_j2ee_x64/lib/jaxrs-api-2.3.2.Final.jar
!/javax/ws/rs/ext/RuntimeDelegate.classtobundle:
//78.0:1/javax/ws/rs/ext/RuntimeDelegate.class

据我所知,LinkageError很可能与RESTeasy使用一些类加载器技巧初始化RuntimeDelegate的方式有关,这可能属于OSGi框架的限制。 我怀疑首先提到的java.lang.ClassCastException具有相同的源。

有没有办法让RESTeasy在OSGi中运行?

PS:关于RESTeasy的类似问题的讨论,但在OSGi之外: java.lang.LinkageError:ClassCastException

更新:这些是包含在restclient包中的 :activation-1.1.jar commons-codec-1.2.jar commons-httpclient-3.1.jar commons-io-2.1.jar commons-logging-1.0.4.jar flexjson-2.1。 jar httpclient-4.1.2.jar httpcore-4.1.2.jar javassist-3.12.1.GA.jar jaxb-api-2.2.3.jar jaxb-impl-2.2.4.jar jaxrs-api-2.3.2。 Final.jar jcip-annotations-1.0.jar jettison-1.3.1.jar jsr250-api-1.0.jar junit-4.10.jar log4j-1.2.14.jar resteasy-jaxb-provider-2.3.2.Final.jar resteasy -jaxrs-2.3.2.Final.jar resteasy-jettison-provider-2.3.2.Final.jar scannotation-1.0.3.jar slf4j-api-1.6.4.jar slf4j-log4j12-1.6.4.jar myservice- common-0.1.0.3.jar my-service-client-0.1.0.3-SNAPSHOT.jar stax-api-1.0-2.jar xmlpull-1.1.3.1.jar xpp3_min-1.1.4c.jar xstream-1.4.2.jar

这些是来自restclient包的导出 :javax.ws.rs,javax.ws.rs.ext,javax.ws.rs.core,org.jboss.resteasy.client,org.jboss.resteasy.client.cache,org .jboss.resteasy.client.extractors,org.jboss.resteasy.client.marshallers,org.jboss.resteasy.client.core.executors,javax.xml.bind.annotation,org.jboss.resteasy.plugins.providers,org .jboss.resteasy.plugins.providers.jaxb,org.jboss.resteasy.spi

看一下SpringSource Bundle Repo ,它有一些非常有用的预构建的公共库包,包括我们正在使用的Apache HTTP Client (与gson一起)来完成我们的RESTful通信。

(遗憾的是我项目的遗留模块仍然使用OSGi,但现在使用RESTeasy 3.0.16)

当我需要OSGify一个依赖项时,我现在的首选解决方案是使用优秀的Apache Ops4j Pax Tipi项目来包装它。

该项目提供了一个预先配置的Maven设置(父POM处理捆绑),你只需要在一个带有org.apache.ops4j.pax.tipi前缀的Tipi子模块中调整原始项目的GAV坐标,并构建新的bundle项目它绘制了原始依赖项,解压缩并将其包装为OSGi包。

您可以从最符合项目设置(依赖关系等)的现有Tipi子项目开始,并调整任何缺少的OSGi导入/导出(最常见的是,这些都是由maven-bundle-plugin自动创建的)。

只要原始项目没有包含太多异国情况或格式错误的依赖项,这对我来说效果很好。

然而,正如我目前所经历的那样,你可能会遇到使用root包的传递依赖性等障碍,这可能是一个真正的显示阻塞(找出哪个库是一个真正的噩梦)。

不幸的是,RESTeasy似乎受此影响,因为我得到了完全相同的错误(默认包,即使在将非测试和非提供的依赖项声明为可选后:

默认包'。' Import-Package语法不允许。

将maven-bundle-plugin升级到最新版本3.0.1会产生不同的错误(甚至更少帮助):

[错误] Bundle org.ops4j.pax.tipi:org.ops4j.pax.tipi.resteasy-jaxrs:bundle:3.0.16.Final.1:无法解析bundle native code header中的名称:[ERROR] Error(s )在捆绑配置中找到

更新似乎通过将POM中的Tipi版本升级到1.4.0来解决,测试...

RESTEasy是强制性的吗? 我个人在OSGi中使用平针织 ,它作为客户端和服务器都运行良好。

此问题不仅限于RESTeasy。 它也发生在泽西岛。

之所以发生这种情况,是因为类路径上有两个JAX-RS类副本。
你可以在LinkageError中看到这个:

[java] java.lang.LinkageError:ClassCastException:试图转换jar:file:/ D:/Development/Eclipses/eclipse_4.2_j2ee_x64/lib/jaxrs-api-2.3.2.Final.jar!/ javax / ws / rs /ext/RuntimeDelegate.class to bundle://78.0:1 / javax / ws / rs / ext / RuntimeDelegate.class

即一份副本来自:

d:/Development/Eclipses/eclipse_4.2_j2ee_x64/lib/jaxrs-api-2.3.2.Final.jar

另一个来自OSGI包。

这会导致RuntimeDelegate类出现问题,该类默认使用系统类加载器来创建RuntimeDelegate实现(请参阅javax.ws.rs.ext.FactoryFinder)。

如果通过两个不同的类加载器加载相同的jar,也会出现问题。

有几种解决方法:

  • 从系统类路径中删除jaxrs-api-2.3.2.Final.jar
  • 在进行任何JAX-RS调用之前,将线程上下文类加载器设置为bundle的类加载器。
    FactoryFinder将使用它来加载RuntimeDelegate。
    为了避免通过调用Thread.currentThread()。setContextClassLoader(myBundleClassLoader)来污染代码,可以使用代理包装JAX-RS客户端。 例如,请参阅https://puredanger.github.io/tech.puredanger.com/2007/06/15/classloaders/的Thread上下文类加载器部分

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM