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>
我有一个 Maven OSGi 多模块项目。当 OSGi 从各个项目模块中挑选模块 jar 时,项目运行得非常好。 (查看下面的 1.1.B).
但是,使用第二种方法,bundle.getRegisteredServices()
(查看下面的 1.1.A) returns null 每当我使用 maven-assembly-plugin version : 2.6:
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()
.
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>