Apache Maven Assembly 插件不适用于 OSGi 包

Apache Maven Assembly Plugin not working with OSGi bundles

我有一个 Maven OSGi 多模块项目。当 OSGi 从各个项目模块中挑选模块 jar 时,项目运行得非常好。 (查看下面的 1.1.B).

但是,使用第二种方法,bundle.getRegisteredServices() (查看下面的 1.1.A) returns null 每当我使用 maven-assembly-plugin version : 2.6:

尝试使用存放到中央文件夹 (D:/parent/provider/target/modules)
framework.getBundleContext().installBundle("file:D:/parent/provider/target/modules/OSGiDmHelloWorldProvider-1.0.jar");
framework.getBundleContext().installBundle("file:D:/parent/provider/target/modules/OSGiDmHelloWorldConsumer-1.0.jar");

查看下面的 1.1.C 使用第二种方法的控制台输出。

1.1.A

if (bundle.getRegisteredServices() != null) {
    for (ServiceReference<?> serviceReference : bundle.getRegisteredServices())
        System.out.println("\tRegistered service: " + serviceReference);
}

为什么我无法使用第二种方法访问捆绑包?

GitHub

我在 GitHub HERE 上有一个 SSCCE。 运行 主要class 会显示我的困境

提前谢谢大家。

1.1.B

package main;

import java.net.URISyntaxException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.launch.Framework;
import org.osgi.framework.launch.FrameworkFactory;

public class App {

    public static void main(String[] args) throws BundleException, URISyntaxException {
        App app = new App();
        app.initialize();
    }

    private void initialize() throws BundleException, URISyntaxException {
        Map<String, String> map = new HashMap<String, String>();

        // make sure the cache is cleaned
        map.put(Constants.FRAMEWORK_STORAGE_CLEAN, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);

        map.put("ds.showtrace", "true");
        map.put("ds.showerrors", "true");

        FrameworkFactory frameworkFactory = ServiceLoader.load(FrameworkFactory.class).iterator().next();
        Framework framework = frameworkFactory.newFramework(map);

        System.out.println("Starting OSGi Framework");
        framework.init();

        loadScrBundle(framework);

        framework.getBundleContext().installBundle("file:D:/parent/provider/target/OSGiDmHelloWorldProvider-1.0.jar");
        framework.getBundleContext().installBundle("file:D:/parent/consumer/target/OSGiDmHelloWorldConsumer-1.0.jar");

        for (Bundle bundle : framework.getBundleContext().getBundles()) {
            bundle.start();
            System.out.println("Bundle: " + bundle.getSymbolicName());
            if (bundle.getRegisteredServices() != null) {
                for (ServiceReference<?> serviceReference : bundle.getRegisteredServices())
                    System.out.println("\tRegistered service: " + serviceReference);
            }
        }
    }

    private void loadScrBundle(Framework framework) throws URISyntaxException, BundleException {
        URL url = getClass().getClassLoader().getResource("org/apache/felix/scr/ScrService.class");
        if (url == null)
            throw new RuntimeException("Could not find the class org.apache.felix.scr.ScrService");
        String jarPath = url.toURI().getSchemeSpecificPart().replaceAll("!.*", "");
        System.out.println("Found declarative services implementation: " + jarPath);
        framework.getBundleContext().installBundle(jarPath).start();
    }
}

1.1.C

Starting OSGi Framework
Found declarative services implementation: file:/C:/Users/Revilo/.m2/repository/org/apache/felix/org.apache.felix.scr/1.6.2/org.apache.felix.scr-1.6.2.jar
INFO : org.apache.felix.scr (1):  Version = 1.6.2
DEBUG: Starting ComponentActorThread
Bundle: org.apache.felix.framework
    Registered service: [org.osgi.service.resolver.Resolver]
    Registered service: [org.osgi.service.packageadmin.PackageAdmin]
    Registered service: [org.osgi.service.startlevel.StartLevel]
Bundle: org.apache.felix.scr
    Registered service: [org.apache.felix.scr.ScrService]
    Registered service: [org.osgi.service.cm.ManagedService]
    Registered service: [org.apache.felix.scr.impl.ScrGogoCommand]
Bundle: null
Bundle: null

我做了很多工作才能让你的样本复制问题。

首先你的反应器顺序在父级中是错误的。这就是为什么你必须一直执行 mvn install 的原因。

<modules>
    <module>OSGiDmHelloWorldProvider</module>
    <module>OSGiDmHelloWorldConsumer</module>
    <module>main</module>
    <module>dist</module>
</modules>

接下来,如果您在父项中定义依赖项(例如 JUnit),则无需在子项中重新定义它。

接下来按照惯例把parent标签放在pom的最前面

我看不出有什么理由让您的子模块具有与父模块不同的版本,因此我删除了标签,因此它们都具有来自父模块的 1.0-SNAPSHOT

接下来,您在 OSGiDmHelloWorldProvider 依赖项中的组 ID 错误(应该是 rev)。

    <dependency>
        <groupId>rev</groupId>
        <artifactId>OSGiDmHelloWorldProvider</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

在主模块中,您有一个不在反应器中的依赖项。我猜这只是对示例的疏忽。

    <dependency>
        <groupId>rev</groupId>
        <artifactId>core</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

毕竟,mvn clean package -DskipTests=true 有效。

您的 Main class 中有一个 hard-coded 字符串,显然对我不起作用。 (您可能还想查看免费的 IDEA Community 而不是 Eclipse!)

String baseDir = "D:/standAloneDev/java/workingDir/Sample Projects/Eclipse/Gen/OSGiDmHelloWorld/dist/target/dist-1.0-SNAPSHOT-bin/plugins/";

你应该让这个亲戚。例如

File baseDir = new File("dist/target/dist-1.0-SNAPSHOT-bin/plugins/");
String baseDirPath = baseDir.getAbsolutePath();

loadScrBundle(framework);

File provider = new File(baseDirPath, "OSGiDmHelloWorldProvider-1.0-SNAPSHOT.jar");
File consumer = new File(baseDirPath, "OSGiDmHelloWorldConsumer-1.0-SNAPSHOT.jar");

framework.getBundleContext().installBundle(provider.toURI().toString());
framework.getBundleContext().installBundle(consumer.toURI().toString());

无论如何,在开始之后我注意到 bundle.getSymbolicName().

上的以下 javadoc
Returns the symbolic name of this bundle as specified by its Bundle-SymbolicName manifest header. The bundle symbolic name should be based on the reverse domain name naming convention like that used for java packages.

所以在 MANIFEST.MF of org.apache.felix.scr-1.6.2.jar 你有

Bundle-Name: Apache Felix Declarative Services
Bundle-SymbolicName: org.apache.felix.scr

你没有这个,因为你没有创建清单并将其添加到 jar。

您需要添加一个执行阶段并告诉 jar 插件使用清单:

        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <executions>
                <execution>
                    <id>bundle-manifest</id>
                    <phase>process-classes</phase>
                    <goals>
                        <goal>manifest</goal>
                    </goals>
                </execution>
            </executions>
            <extensions>true</extensions>
            <configuration>
                <instructions>
                    <Bundle-SymbolicName>OSGiDmHelloWorldProvider</Bundle-SymbolicName>
                    <Export-Package>com.bw.osgi.provider.able</Export-Package>
                    <Bundle-Activator>com.bw.osgi.provider.ProviderActivator</Bundle-Activator>
                    <Bundle-Vendor>Baptiste Wicht</Bundle-Vendor>
                </instructions>
            </configuration>
        </plugin>