Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在osgi(Liferay DXP)中使用JAXB 2.2.11_Jaxb_Osgi_Osgi Bundle_Liferay 7 - Fatal编程技术网

如何在osgi(Liferay DXP)中使用JAXB 2.2.11

如何在osgi(Liferay DXP)中使用JAXB 2.2.11,jaxb,osgi,osgi-bundle,liferay-7,Jaxb,Osgi,Osgi Bundle,Liferay 7,我试图在osgi环境(Liferay DXP)中使用JAXB 2.2.11。我在创建JAXBContext时遇到问题。根据在研究和时发现的其他一些源代码,我确定在osgi容器中,我需要为JAXB提供正确的类加载器来实例化上下文。我有这样的代码: ClassLoader cl package.with.jaxb.objects.ObjectFactory.class.getClassLoader(); JAXBContext jc=JAXBContext.newInstance(“package.

我试图在osgi环境(Liferay DXP)中使用JAXB 2.2.11。我在创建JAXBContext时遇到问题。根据在研究和时发现的其他一些源代码,我确定在osgi容器中,我需要为JAXB提供正确的类加载器来实例化上下文。我有这样的代码:

ClassLoader cl package.with.jaxb.objects.ObjectFactory.class.getClassLoader();
JAXBContext jc=JAXBContext.newInstance(“package.with.jaxb.objects”,cl)

此代码导致具有以下堆栈跟踪的空指针异常:

Caused by: java.lang.NullPointerException
    at javax.xml.bind.ContextFinder.handleClassCastException(ContextFinder.java:129)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:201)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:146)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:371)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:446)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:409)
查看源代码,我可以看到第129行的
context
必须为空:

抛出handleClassCastException(context.getClass(),JAXBContext.class)

我认为问题可能在于我的模块依赖于jaxb api 2.2.11,但jaxb impl类是由rt.jar在运行时提供的,可能比2.2.11更新,因为Liferay DXP在JDK 1.8上运行。为了解决这个问题,我尝试将jaxb-impl.jar2.2.11作为依赖项包含在我的osgi模块中,并认为jaxb api和jaxb-impl版本会匹配。之后,尝试使用与上述相同的代码创建JAXBContent会导致以下错误:

ClassCastException: attempting to cast jar:file:/C:/Program%20Files/Java/jdk1.8.0_144/jre/lib/rt.jar!/javax/xml/bind/JAXBContext.class to bundleresource://623.fwk616113009:13/javax/xml/bind/JAXBContext.class. Please make sure that you are specifying the proper ClassLoader.
从该消息的外观来看,正在实例化的JAXBContext来自通过rt.jar加载的JAXBContext版本。这让我非常困惑,因为我希望使用由模块的类加载器加载的JAXBContext版本,因为我在模块中包含了jaxb-impl.jar,并且我已经指定在调用JAXBContext.newInstance时使用模块的类加载器。有人能告诉我如何让JAXB2.2.11在osgi容器中工作吗


*请注意,我无法升级我的模块使用的jaxb api版本,因为jaxb代码实际上位于需要jaxb 2.2.11的第三方jar中(我刚刚通过编写一些测试jaxb代码从等式中删除了第三方jar)。

最好的地方是ApacheKaraf。它不安装任何JAXB-API捆绑包,而是使用
org.apache.servicemix.specs.JAXB-API-2.2-2.7.0.jar
内部
lib/approved
目录

这样,您就不会使用
rt.jar
提供的JAXB-API

对于实现,最好使用ServiceMix版本的JAXB捆绑包:

  • bundles:org.apache.servicemix.bundles.jaxb impl:2.2.111
  • org.apache.servicemix.bundles:org.apache.servicemix.bundles.jaxbxjc:2.2.111

经过广泛研究,我找到了以下解决方案。因为它看起来像是通过bundle类加载器,正如在中被接受的答案所建议的那样,必须是正确的,所以我沿着这条路径,试图找出为什么我会得到一个NullPointerException。在仔细查看jaxb api的源代码以跟踪NullPointerException的堆栈跟踪之后,我可以看到jaxb api代码做了如下事情

classLoader.loadClass(“com.sun.xml.internal.bind.v2.ContextFactory”)

其中,
classLoader
是我的包的类加载器(因为这是我传入的),而
ContextFactory
实际上是jaxb impl中的一个类,由引导类加载器加载。这就是问题所在,因为我的 bundle的类加载器将无法看到引导类加载器加载的类。这让我感到很困惑,因为我不习惯osgi中类装入器的工作方式。我错误地认为引导类加载器加载的类是可见的,因为我习惯于在有委托的情况下加载web应用程序类。在osgi类装入器中 它们彼此完全隔离,只有在导出时才可见。为了回避这个问题,我发现自己在谈论类似的问题。原来有一个概念 在osgi中调用boot delegation,您可以指定始终通过引导类加载器加载的类/包的列表。因此,最终结果是两个步骤:

1) 在调用代码获取JAXBContext之前,将线程的类装入器切换到bundle类装入器:

ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();

try {           
    // ObjectFactory here is in the same package as my classes to be marshalled
    ClassLoader objectFactoryClassLoader = ObjectFactory.class.getClassLoader();            
    Thread.currentThread().setContextClassLoader(objectFactoryClassLoader);
    // JAXB code goes here
} finally {
    Thread.currentThread().setContextClassLoader(currentClassLoader);
}
2) 指定要使用引导委派机制加载的包。此列表需要包括需要加载的类的可传递依赖项。在我的例子中,我使用的是Liferay,所以列表 特定于Liferay,它位于portal-ext.properties配置文件中。幸运的是,我找到了有人为我完成大部分工作的地方:

module.framework.properties.org.osgi.framework.bootdelegation=\
  __redirected,\
  com.liferay.aspectj,\
  com.liferay.aspectj.*,\
  com.liferay.portal.servlet.delegate,\
  com.liferay.portal.servlet.delegate*,\
  com.sun.ccpp,\
  com.sun.ccpp.*,\
  com.sun.crypto.*,\
  com.sun.image.*,\
  com.sun.jmx.*,\
  com.sun.jna,\
  com.sun.jndi.*,\
  com.sun.mail.*,\
  com.sun.management.*,\
  com.sun.media.*,\
  com.sun.msv.*,\
  com.sun.org.*,\
  com.sun.syndication,\
  com.sun.tools.*,\
  com.sun.xml.*,\
  com.yourkit.*,\
  org.eclipse.persistence.internal.jaxb,\
  org.eclipse.persistence.internal.jaxb.*,\
  javax.xml.*,\
  sun.*
有用链接:


以下是我使用JDK 11、Liferay DXP/7.2、OSGI以及从Dev Studio创建的示例Jax RS web服务的变通方法。尝试访问web服务时,我遇到的错误如下:

发生JAXBEException:未找到JAXB-API的实现 在模块路径或类路径上。。 找不到com.sun.xml.internal.bind.v2.ContextFactory org.apache.aries.jax.rs.whiteboard_1.0.4

对我来说,有效的方法是在系统级别定义上下文工厂,以覆盖预定义的上下文工厂。将以下系统变量添加到系统中

javax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory
例如,您可以将其添加到Tomcat中的setenv.sh/bat文件中,或者在eclipse中,您可以在VM参数下访问服务器启动配置的参数选项卡

-Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory
这在不添加任何额外库的情况下起作用,因为Liferay已经包含了这些库

这是怎么回事?请参阅并阅读JAXB实现的发现部分。使用/META-INF/services/javax.xml.bind.JAXBContext文件对我不起作用

我希望这对某人有帮助。
DXP用户的最后一个注意事项是,如果您的服务被拒绝,那么您需要阅读

感谢您回答Grzegorz。不幸的是,正如我在文章末尾提到的,我不知道该怎么做