我正在构建一些我希望作为OSGi包公开的模块,而没有任何与OSGi库的实际依赖关系。看来这可以使用声明性服务选项。
但是因为我对OSGi很新(至少在创建捆绑包方面)我想测试它是否一切正常,为此我想建立一个小的嵌入式OSGi环境。
目前我有一个捆绑包可以导出API,还提供单个界面的存根实现。
我已按照以下教程设置环境:
嵌入式felix实现似乎正常工作,但有两个问题:
Bundle bundle = felix.getBundleContext().installBundle("/path/to/bundle.jar")
bundle.start();
System.out.println(bundle.getRegisteredServices());
这打印出null
,所以当捆绑看起来好了,它似乎没有公开任何服务。
其次,我想知道是否必须做一些特殊的事情才能使声明性服务更新并运行。我的maven依赖是:
<dependencies>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
<version>4.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr</artifactId>
<version>1.6.2</version>
</dependency>
</dependencies>
我尝试将这个包添加到felix启动属性中:
map.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "org.apache.felix.scr; version=1.6.2");
然而,乍一看似乎有点乐观。如何为嵌入式felix引擎启用声明性服务?
答案 0 :(得分:6)
这两个问题的解决方案是在加载我自己的bundle之前将“scr”jar(用于解析声明性服务)加载为bundle。
因为jar位于我的maven存储库中并且它应该跨系统工作,所以下面的代码从它所在的任何地方加载scr jar:
URL url = getClass().getClassLoader().getResource("org/apache/felix/scr/ScrService.class");
String jarPath = url.toURI().getSchemeSpecificPart().replaceAll("!.*", "");
framework.getBundleContext().installBundle(jarPath).start();
在此位之后,我加载了自己的包,并且正确检测到其中的服务。
在旁注中,您可以通过向初始地图添加一些属性来启用日志记录:
map.put("ds.showtrace", "true");
map.put("ds.showerrors", "true");
可以在http://felix.apache.org/documentation/subprojects/apache-felix-service-component-runtime.html
找到更多属性为了将来参考,以下是我用来启动和运行的所有代码
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);
// more properties available at: http://felix.apache.org/documentation/subprojects/apache-felix-service-component-runtime.html
map.put("ds.showtrace", "true");
map.put("ds.showerrors", "true");
System.out.println("Building OSGi Framework");
FrameworkFactory frameworkFactory = ServiceLoader.load(FrameworkFactory.class).iterator().next();
Framework framework = frameworkFactory.newFramework(map);
System.out.println("Starting OSGi Framework");
framework.start();
// declarative services dependency is necessary, otherwise they won't be picked up!
loadScrBundle(framework);
framework.getBundleContext().installBundle("file:/path/to/myBundle.jar").start();
ServiceReference reference = framework.getBundleContext().getServiceReference("my.Interface");
System.out.println(framework.getBundleContext().getService(reference));
for (Bundle bundle : framework.getBundleContext().getBundles()) {
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)
我建议你看看pax exam。它允许在OSGi容器中测试您的包。 好处是它与junit集成,因此您的测试看起来与普通测试非常相似。有些示例请参阅Apache Karaf Tests。