在感觉自己掌握了 OSGi 的使用方式之后,我尝试向使用 apache felix 并与 maven-bundle-plugin 捆绑的应用程序添加第 3 方依赖项(特别是 log4j2)。不幸的是,我似乎陷入了依赖 hell 。
我尝试过使用多种 maven-bundle 策略,例如 Import-Package、Embed-Dependency、wrapImportPackage、Embed-Transitive,以及设置特定版本号(仅举几例)。下面是这个插件的 pom 的样子:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ParentId</artifactId>
<groupId>ParentGroupId</groupId>
<version>x.x.x</version>
</parent>
<groupId>ParentGroupId.ParentId</groupId>
<artifactId>thisModule</artifactId>
<packaging>bundle</packaging>
<name>thisModule</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>AM</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>3.5.1</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.name}</Bundle-SymbolicName>
<Bundle-Activator>moduleActivator</Bundle-Activator>
<Embed-Dependency>
AM,
gson,
log4j-api,
log4j-core
</Embed-Dependency>
</instructions>
</configuration>
</plugin>
</plugins>
<finalName>${project.artifactId}</finalName>
</build>
我觉得我取得的最大进展是上面的 pom,我将 log4j api 和核心直接嵌入到 bundle 中,但似乎 OSGi 无法下载和捆绑 log4j 的编译依赖项api和core是依赖的。它使用 maven 成功构建,但是当我部署 EAR 和 JAR 时,我在运行时收到此错误(当插件尝试启动时):
Caused By: org.osgi.framework.BundleException: Unresolved constraint in bundle thisModule [2]: Unable to resolve 2.0: missing requirement [2.0] package; (package=com.conversantmedia.util.concurrent)
将命名 log4j 所需的特定依赖项的错误。我不想做的是将每个依赖项及其母亲包含在 Embed-Dependency
中标签。
我在这里做错了什么?
另请注意:由于限制,我唯一的选择是使用 apache felix 和 OSGi。
下面是我对上述 POM 所做的修改的其他示例及其结果输出:
- 同时删除
log4j-api
和log4j-core
来自Embed-Dependency
并添加<wrapImportPackage>;</wrapImportPackage>
标签。这样做会产生以下输出,这种输出非常常见,每当我尝试导入时都会发生:
Caused By: org.osgi.framework.BundleException: Unresolved constraint in bundle thisModule [2]: Unable to resolve 2.0: missing requirement [2.0] package; (&(package=org.apache.logging.log4j)(version>=2.12.0)(!(version>=3.0.0)))
- 将 * 添加到
Embed-Dependency
以及添加<Embed-Transitive>true</Embed-Transitive>
:
Caused By: org.osgi.framework.BundleException: Unresolved constraint in bundle thisModule [2]: Unable to resolve 2.0: missing requirement [2.0] package; (package=android.dalvik)
最佳答案
嵌入日志库是一个坏主意。毕竟,您希望在一个中心位置配置日志记录,当每个包都嵌入一个日志记录框架时,这是非常困难的。
在大多数情况下,安全的选择是简单地将 maven-bundle-plugin 配置保留为空并让它做它的事情。
我个人总是使用 slf4j 来登录 OSGi。您只需依赖 slf4j-api。 maven-bundle-plugin 自动创建导入包语句。
然后在运行时,您只需部署一个支持您想要的日志记录 API 的日志记录框架即可。
对于 apache karaf,默认情况下已经是这种情况。如果您使用 bndtools 或您自己的基于普通 felix 的应用程序组件,请查看我的 osgi best practices example 。 它展示了如何在您自己的 bundle 中使用 slf4j-api,以及如何在基于 karaf 和 bndtools 的应用程序中配置日志系统。
关于osgi - 在 Maven OSGi 包中使用第 3 方依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58884266/