我尝试使用 POM 优先方法将 JAXB 模块作为 OSGi bundle 与 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
,但是从 XSD 生成 POJO 类的 Maven 插件在撰写本文时似乎尚未准备好( org.jvnet.jaxb2.maven2:maven-jaxb2-plugin
和 org.codehaus.mojo:jaxb2-maven-plugin
都没有)。
我的问题:
- 在哪里可以获得
com.sun.xml.bind
来自? - 怎么办
jaxb-osgi
和jaxb-impl
模块相关吗? - 这一切应该如何运作?
- 我该如何继续?
更新 - 背景信息
我有以下基于 Extender Pattern 的设置:
- 核心扩展模块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
包(参见 issue )和 Apache Aries SPI Fly Dynamic Weaving Bundle (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
为什么它尝试加载硬编码的默认值 com.sun.xml.bind.v2.ContextFactory
而不是com.sun.xml.bind.v2.JAXBContextFactory
通过ServiceLoader?
最佳答案
由于每个 OSGI 包都使用自己的类加载器,因此 JAXB API 无法使用标准 ServiceLoader
来定位 JAXB 实现。但是,从版本 2.2.2 开始,JAXB API 可以使用 osgi-resource-locator作为后备。
因此,为了在 Java 11 上使用 JAXB,您只需:
- 添加对
javax.xml.bind
和org.glassfish.hk2.osgiresourcelocator
软件包的依赖项, - 部署
osgi-resource-locator
和jaxb-osgi
与您的 bundle 一起捆绑。
备注:如果您想使用 MOXy,则需要额外的步骤,因为 MOXy 不附带 META-INF/services/javax.xml.bind.JAXBContext
文件(参见 this answer )。
关于java - JAXB + OSGi 与 Java 11,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65868619/