JAXB + OSGi with Java 11



我正在尝试使用POM-first方法(生成OSGi元数据)将JAXB模块加载为Java 11和Apache Felix的OSGi包。

首先我尝试了:

<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-osgi</artifactId>
<version>2.3.3</version>
</dependency>

但是这给了我以下运行时异常:

SCHWERWIEGEND: Implementation of JAXB-API has not been found on module path or classpath.  
javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
- with linked exception: 
[java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory]

这可能与以下问题有关,但我不确定:https://github.com/eclipse-ee4j/jaxb-api/issues/78

所以我尝试了v3.0.0,但现在我的一个注释处理程序使用JAXB生成XML文档,失败了:

Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project my-module: Compilation failure
Implementation of JAXB-API has not been found on module path or classpath.

我注意到jaxb-osgi-3.0.0.jar不再提供com.sun.xml.bind包了

我也试图从javax.xml.bind迁移到jakarta.xml.bind,但是Maven插件,从xsd生成POJO类,似乎还没有准备好在写作的时候(既不是org.jvnet.jaxb2.maven2:maven-jaxb2-plugin也不是org.codehaus.mojo:jaxb2-maven-plugin)。

我的问题:

  1. 我从哪里可以得到com.sun.xml.bind?
  2. jaxb-osgijaxb-impl模块是如何关联的?
  3. 这是怎么回事?
  4. 我该如何继续?

更新-背景信息

我有以下基于扩展器模式的设置:

  • 核心扩展模块M:
    • 提供一些JAXB类
    • 一个BundleTracker,用于从一些bundle X, Y, Z的META-INF子目录中解编组XML文档
    • 一个抽象的自定义注释处理器,用于编组XML文档
  • 扩展模块A、B、C:
    • 提供额外的JAXB类(从xsd生成)
    • 扩展是使用声明式服务
    • 注册的
    • 自定义注解
    • 注释处理器将注释属性转换为基于JAXB的模型,并在预期位置生成xml文档
  • 扩展模块X, Y, Z
    • 使用模块A, B, C的注释
    • 使用A、B、C的注释处理器生成xml文档

目标:应该很容易创建扩展模块,如X, Y, Z

在Java SE 8中一切正常,其中JAXB仍然与JRE捆绑在一起。

更新1

因为Maven插件还没有准备好,我现在坚持使用v2.3.3。

我修改了以下内容:

  • 我在调用JAXBContext.newInstance时提供了一个类加载器

  • 我在maven-bundle-plugin的几个模块中添加了以下配置:

    com.sun.xml.bind。v2, *

这解决了java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory的问题(这似乎不是正确的解决方案,虽然),但现在无法找到ObjectFactory,尽管它们已生成。

更新2

我现在使用修改的jaxb-osgi包(见问题)和Apache Aries SPI Fly动态编织包(1.3.2)(OSGi ServiceLoader Mediator规范的参考实现),我向核心模块M添加了以下要求:

Require-Capability: [...],osgi.extender;filter:="(o
sgi.extender=osgi.serviceloader.processor)",osgi.serviceloader;filter:=
"(osgi.serviceloader=javax.xml.bind.JAXBContextFactory)";cardinality:=m
ultiple,[...]"

服务似乎被检测到:

2021-02-13 12:09:31 INFO org.apache.aries.spifly.BaseActivator log - Registered provider com.sun.xml.bind.v2.JAXBContextFactory of service javax.xml.bind.JAXBContextFactory in bundle com.sun.xml.bind.jaxb-osgi
2021-02-13 12:09:31 INFO org.apache.aries.spifly.BaseActivator log - Registered provider com.sun.tools.xjc.addon.code_injector.PluginImpl of service com.sun.tools.xjc.Plugin in bundle com.sun.xml.bind.jaxb-osgi
2021-02-13 12:09:31 INFO org.apache.aries.spifly.BaseActivator log - Registered provider com.sun.tools.xjc.addon.locator.SourceLocationAddOn of service com.sun.tools.xjc.Plugin in bundle com.sun.xml.bind.jaxb-osgi
2021-02-13 12:09:31 INFO org.apache.aries.spifly.BaseActivator log - Registered provider com.sun.tools.xjc.addon.sync.SynchronizedMethodAddOn of service com.sun.tools.xjc.Plugin in bundle com.sun.xml.bind.jaxb-osgi
2021-02-13 12:09:31 INFO org.apache.aries.spifly.BaseActivator log - Registered provider com.sun.tools.xjc.addon.at_generated.PluginImpl of service com.sun.tools.xjc.Plugin in bundle com.sun.xml.bind.jaxb-osgi
2021-02-13 12:09:31 INFO org.apache.aries.spifly.BaseActivator log - Registered provider com.sun.tools.xjc.addon.episode.PluginImpl of service com.sun.tools.xjc.Plugin in bundle com.sun.xml.bind.jaxb-osgi
2021-02-13 12:09:31 INFO org.apache.aries.spifly.BaseActivator log - Registered provider com.sun.tools.xjc.addon.accessors.PluginImpl of service com.sun.tools.xjc.Plugin in bundle com.sun.xml.bind.jaxb-osgi

但是我仍然得到:

javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
- with linked exception:
[java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory not found by 

为什么它试图通过ServiceLoader加载硬编码的默认com.sun.xml.bind.v2.ContextFactory而不是com.sun.xml.bind.v2.JAXBContextFactory?

因为每个OSGI包都使用自己的类加载器,所以JAXB API不能使用标准的ServiceLoader来定位JAXB实现。但是,从2.2.2版本开始,JAXB API可以使用osgi-resource-locator作为回退。

因此,为了在Java 11上使用JAXB,您只需要:
  1. 添加对javax.xml.bindorg.glassfish.hk2.osgiresourcelocator包的依赖,
  2. osgi-resource-locatorjaxb-osgi包与您的包一起部署。

评论:如果你想使用MOXy,你需要额外的步骤,因为MOXy没有随META-INF/services/javax.xml.bind.JAXBContext文件一起发布(参见这个答案)。

最新更新