在 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 及其结果输出所做的其他修改示例:

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)))

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 的应用程序中配置日志系统。