Using Service Component Runtime

落花浮王杯 提交于 2019-12-23 01:51:34

问题


I goal is to remove dependencies on OSGi from my bundles. I use felix (v 4.2.1) as impl and run it embeddable. I install org.apache.felix.scr (v. 1.6.2) bundle to have Service Component Runtime support. But when I run

 ServiceReference ref = bundleContext().getServiceReference(ScrService.class.getName());
 ScrService s = (ScrService) bundleContext().getService(ref);

I get ClassCastException: org.apache.felix.scr.impl.ComponentRegistry cannot be cast to org.apache.felix.scr.ScrService.

Okay. I will modify System Packages.

config.put(Constants.FRAMEWORK_SYSTEMPACKAGES, "org.apache.felix.scr");

Now I get

Caused by: org.osgi.framework.BundleException: Unresolved constraint in bundle org.apache.felix.scr [1]: Unable to resolve 1.0: missing requirement [1.0] osgi.wiring.package; (&(osgi.wiring.package=org.osgi.framework)(version>=1.4.0)(!(version>=2.0.0)))
        at org.apache.felix.framework.Felix.resolveBundleRevision(Felix.java:3974)
        at org.apache.felix.framework.Felix.startBundle(Felix.java:2037)
        at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:955)
        at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:942)
        at com.copyright.rup.communications.felix.Felix.addBundle(Felix.java:86)
        ... 28 more

How can I solve it?


回答1:


I suspect your first block where you try to get hold of ScrService is on the embedding side (i.e. outside of the framework, not from within an installed bundle).

If this is the case, then you have two copies of the ScrService - one loaded from your embedding code's ClassLoader and one loaded by ClassLoader of the scr bundle when it's resolved by the framework. This is why you're seeing the ClassCastException.

You can just export what the SCR bundle's exports from the framework bundle.

Section 3.8, page 51 of the OSGi Core spec v5 states that in resolution of bundle wiring if a module has both import and export definitions of the same package then the framework will first try to resolve externally and if successful discard the overlapping export definition.

So copy the SCR runtime bundle's Export-Package manifest header as a framework property:

properties.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, 
        "org.ops4j.pax.url.mvn,org.apache.felix.scr;uses:=\"org.osgi.framework," +
        "org.osgi.service.component\";version=\"1.7\"," +
        "org.apache.felix.scr.component;status=provisional;mandatory:=status;" +
        "uses:=\"org.osgi.service.component\";version=\"1.0\"," +
        "org.osgi.service.component;uses:=\"org.osgi.framework\";version=\"1.2\"");

//Which you pass to the FrameworkFactory ...

ServiceLoader<FrameworkFactory> loader = ServiceLoader.load(FrameworkFactory.class);
Iterator<FrameworkFactory> iterator = loader.iterator();
Framework framework = iterator.next().newFramework(properties);
framework.start();

A couple of things to note:

  • If you're not already using ConfigurationAdmin, then also install org.osgi.compendium to ensure you have at least have the API classes for org.osgi.service.cm.* and org.osgi.service.metatype*, AFAIK these are necessary for the SCR runtime.

  • You shouldn't use Constants.FRAMEWORK_SYSTEMPACKAGES unless you're seriously customising the actual framework, instead you'd probably want to use Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA to extend what is exported by the framework bundle. (The framework implementations have pretty good defaults for FRAMEWORK_SYSTEMPACKAGES and it's normally unnecessary to modify this when embedding).



来源:https://stackoverflow.com/questions/16150855/using-service-component-runtime

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!