在 OSGI Bundle 中创建 JAXBContext 的问题

Posted

技术标签:

【中文标题】在 OSGI Bundle 中创建 JAXBContext 的问题【英文标题】:Problems creating JAXBContext in OSGI Bundle 【发布时间】:2017-06-11 16:06:45 【问题描述】:

任务:转换数据并将结果作为 XML 文件存储在磁盘上的批处理。

问题:编组对象,在 OSGI 包中加载 JAXBContextFactory。 由 FutureTask:311 中的 java.lang.NoClassDefFoundError: org/eclipse/persistence/internal/libraries/asm/ClassWriter 引起的死锁。没有堆栈跟踪或原因。

问题:为了让 JAXBContext 实例化工作,我错过了什么样的设置或导入?

解释:

对于数据处理,我需要将我的 POJO 类作为 XML 文件存储在磁盘上。 POJO 类是从一个 xsd 文件生成的,该文件在批处理过程中填充了 jaxb2-maven-plugin (xjc),然后保存到磁盘中进行进一步处理。

从另一个 Stack Overflow 问题中,我了解到 OSGI 使用不同的类加载器,我必须使用正确的 newInstance 方法来实例化 JAXBContext。 (答案:https://***.com/a/1043807/7461710)。

这是我当前的 newInstance 调用,PrintDocument 类在自动生成的包com.some.package.generated 中,而 ObjectFactory 在同一个包中,也是由 jaxb2-maven-plugin 生成的。 程序在 newInstance 调用期间失败。

JAXBContext jaxbContext = JAXBContext.newInstance(PrintDocument.class.getPackage().getName(),
            ObjectFactory.class.getClassLoader());
    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

日志文件:

DEBUG XMLUtil:24 -Step 4/4: Save result into file. path: /somewhere/result.xml
DEBUG bind:282 - Searching jaxb.properties
DEBUG bind:300 - Searching the system property
DEBUG bind:565 - Trying to load org.eclipse.persistence.jaxb.JAXBContextFactory
[no further output]

我们使用bnd来导入包,我已经将bundle中的bnd.bnd文件设置为

Import-Package: \
    org.eclipse.persistence.jaxb,\
    *

作为 JAXB 实现,我使用 moxy。

如果我将这个 jaxb.properties 文件添加到生成的 pojo 包中:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

抛出常规类未找到异常。即使在我的单元测试中。 (单元测试在 OSGI 包之外执行编组)

javax.xml.bind.JAXBException: Provider org.eclipse.persistence.jaxb.JAXBContextFactory  not found
 - with linked exception:
[java.lang.ClassNotFoundException: org.eclipse.persistence.jaxb.JAXBContextFactory ]
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:134)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:293)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:431)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:394)
    [...]

但是,如果我根据这个答案 https://***.com/a/6820113/7461710 将 newInstance 调用更改为 JAXBContextFactory.createContext,我的单元测试会再次运行,并且程序会陷入由 java.lang.NoClassDefFoundError: org/eclipse/persistence/internal/libraries/asm/ClassWriter 引起的死锁,如上所述。

项目依赖:

<dependency>
    <groupId>biz.aQute.bnd</groupId>
    <artifactId>biz.aQute.launcher</artifactId>
    <version>3.3.0</version>
</dependency>
<dependency>
    <groupId>org.eclipse.platform</groupId>
    <artifactId>org.eclipse.osgi</artifactId>
    <version>3.11.2</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.5</version>
</dependency>
<dependency>
    <groupId>org.ops4j.pax.logging</groupId>
    <artifactId>pax-logging-api</artifactId>
    <version>1.9.1</version>
</dependency>
<dependency>
    <groupId>org.ops4j.pax.logging</groupId>
    <artifactId>pax-logging-service</artifactId>
    <version>1.9.1</version>
</dependency>
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20160810</version>
</dependency>
<dependency>
    <groupId>org.zeroturnaround</groupId>
    <artifactId>zt-exec</artifactId>
    <version>1.9</version>
</dependency>
<dependency>
    <groupId>com.io7m.xom</groupId>
    <artifactId>xom</artifactId>
    <version>1.2.10</version>
</dependency>
<dependency>
    <groupId>org.ops4j.pax.jdbc</groupId>
    <artifactId>pax-jdbc</artifactId>
    <version>0.9.0</version>
    <exclusions>
        <exclusion>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.compendium</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.ops4j.pax.jdbc</groupId>
    <artifactId>pax-jdbc-h2</artifactId>
    <version>0.4.0</version>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.193</version>
</dependency>
<dependency>
    <groupId>org.ops4j.pax.jdbc</groupId>
    <artifactId>pax-jdbc-oracle</artifactId>
    <version>0.9.0</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.5</version>
</dependency>
<dependency>
    <groupId>org.osgi</groupId>
    <artifactId>org.osgi.core</artifactId>
    <version>6.0.0</version>
</dependency>
<dependency>
    <groupId>org.osgi</groupId>
    <artifactId>osgi.cmpn</artifactId>
    <version>6.0.0</version>
</dependency>
<dependency>
    <groupId>org.apache.felix</groupId>
    <artifactId>org.apache.felix.scr</artifactId>
    <version>2.0.6</version>
</dependency>
<dependency>
    <groupId>org.apache.servicemix.bundles</groupId>
    <artifactId>org.apache.servicemix.bundles.asm</artifactId>
    <version>3.3.1_1</version>
</dependency>
<dependency>
    <groupId>org.apache.servicemix.bundles</groupId>
    <artifactId>org.apache.servicemix.bundles.saxon</artifactId>
    <version>9.7.0-10_1</version>
</dependency>
<dependency>
    <groupId>xml-resolver</groupId>
    <artifactId>xml-resolver</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>org.apache.felix</groupId>
    <artifactId>org.apache.felix.configadmin</artifactId>
    <version>1.8.12</version>
</dependency>
<dependency>
    <groupId>org.apache.felix</groupId>
    <artifactId>org.apache.felix.gogo.shell</artifactId>
    <version>1.0.0</version>
</dependency>
<dependency>
    <groupId>org.apache.felix</groupId>
    <artifactId>org.apache.felix.gogo.command</artifactId>
    <version>1.0.0</version>
    <exclusions>
        <exclusion>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.compendium</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.apache.felix</groupId>
    <artifactId>org.apache.felix.gogo.runtime</artifactId>
    <version>1.0.0</version>
</dependency>
<dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>org.eclipse.persistence.moxy</artifactId>
    <version>2.6.4</version>
</dependency>

【问题讨论】:

我没有使用 moxy 的经验,但是 jre 的 JAXB 支持对我来说很好。你试过这个吗? @ChristianSchneider 我应该在 jaxb.properties 中设置我的 JAXBContextFactory 到哪个包? javax.xml.bind.JAXBContextFactory 不工作 【参考方案1】:

默认是com.sun.xml.internal.ws.developer.JAXBContextFactory,但你不应该在你的bundle中设置它,因为它是一个sun私有包。

尝试在您的 OSGi 框架属性中使用它:

org.osgi.framework.bootdelegation=com.sun.*

这将允许 JAXBContext 找到一个实例化默认的 JAXBContextImpl。

【讨论】:

以上是关于在 OSGI Bundle 中创建 JAXBContext 的问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在eclipse中基于maven创建osgi的bundle

让 OSGi 服务使用最新版本的 bundle,即使安装了多个 bundle 版本

在 Liferay 7 中创建自定义标签库

使用 maven-bundle-plugin 安装 OSGi 依赖项

OSGI 包中 Bundle-Classpath 的预期用例是啥

在 Eclipse 中安装东西 - 找不到存储库“osgi.bundle”