在 Maven OSGi 包中使用第三方依赖
Using a 3rd party dependency within a Maven OSGi bundle
在感觉我掌握了如何使用 OSGi 之后,我尝试着手向我使用 apache felix 并与 maven-bundle-plugin 捆绑在一起的应用程序添加第 3 方依赖项,特别是 log4j2。不幸的是,我似乎陷入了依赖地狱。
我尝试过使用多种 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 和核心直接嵌入到包中,但似乎 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 及其结果输出所做的其他修改示例:
- 从
Embed-Dependency
中删除 log4j-api
和 log4j-core
并添加 <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。
它展示了如何在您自己的包中使用 slf4j-api,以及如何在基于 karaf 和 bndtools 的应用程序中配置日志系统。
在感觉我掌握了如何使用 OSGi 之后,我尝试着手向我使用 apache felix 并与 maven-bundle-plugin 捆绑在一起的应用程序添加第 3 方依赖项,特别是 log4j2。不幸的是,我似乎陷入了依赖地狱。
我尝试过使用多种 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 和核心直接嵌入到包中,但似乎 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 及其结果输出所做的其他修改示例:
- 从
Embed-Dependency
中删除log4j-api
和log4j-core
并添加<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。 它展示了如何在您自己的包中使用 slf4j-api,以及如何在基于 karaf 和 bndtools 的应用程序中配置日志系统。