问题
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 fororg.osgi.service.cm.*
andorg.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 useConstants.FRAMEWORK_SYSTEMPACKAGES_EXTRA
to extend what is exported by the framework bundle. (The framework implementations have pretty good defaults forFRAMEWORK_SYSTEMPACKAGES
and it's normally unnecessary to modify this when embedding).
来源:https://stackoverflow.com/questions/16150855/using-service-component-runtime