Java 使用服务组件运行时

Java 使用服务组件运行时,java,osgi,apache-felix,Java,Osgi,Apache Felix,我的目标是从捆绑包中删除对OSGi的依赖。我使用felix(V4.2.1)作为impl并运行它可嵌入。我安装了org.apache.felix.scr(v.1.6.2)捆绑包以获得服务组件运行时支持。但是当我跑的时候 ServiceReference ref = bundleContext().getServiceReference(ScrService.class.getName()); ScrService s = (ScrService) bundleContext().getServ

我的目标是从捆绑包中删除对OSGi的依赖。我使用felix(V4.2.1)作为impl并运行它可嵌入。我安装了
org.apache.felix.scr
(v.1.6.2)捆绑包以获得服务组件运行时支持。但是当我跑的时候

 ServiceReference ref = bundleContext().getServiceReference(ScrService.class.getName());
 ScrService s = (ScrService) bundleContext().getService(ref);
我得到
ClassCastException:org.apache.felix.scr.impl.ComponentRegistry不能强制转换为org.apache.felix.scr.ScrService

好的。我将修改系统包

config.put(Constants.FRAMEWORK_SYSTEMPACKAGES, "org.apache.felix.scr");
现在我明白了

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

我该如何解决它呢?

我怀疑您尝试获取
ScrService
的第一个块位于嵌入端(即框架外部,而不是安装包内部)

如果是这种情况,那么您有两份
ScrService
——一份从嵌入代码的类加载器加载,另一份在框架解析后由scr包的类加载器加载。这就是为什么您会看到
ClassCastException

您可以只导出SCR捆绑包从框架捆绑包导出的内容

第51页第3.8节指出,在解决线束布线时,如果模块具有相同包的导入和导出定义,则框架将首先尝试外部解决,如果成功,则放弃重叠导出定义

因此,将SCR运行时捆绑包的导出包清单头复制为框架属性:

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();
properties.put(Constants.FRAMEWORK\u SYSTEMPACKAGES\u EXTRA,
“org.ops4j.pax.url.mvn,org.apache.felix.scr;使用:=\”org.osgi.framework,”+
“org.osgi.service.component\”版本=“1.7\”+
“org.apache.felix.scr.component;状态=临时;必需:=状态;”+
“使用:=\”org.osgi.service.component\“;版本=\”1.0\”+
“org.osgi.service.component;使用:=\”org.osgi.framework\“version=”1.2\”;
//你把它交给框架工厂。。。
ServiceLoader=ServiceLoader.load(FrameworkFactory.class);
迭代器迭代器=loader.Iterator();
frameworkframework=iterator.next().newFramework(属性);
framework.start();
有几件事需要注意:

  • 如果您尚未使用
    ConfigurationAdmin
    ,请同时进行安装,以确保您至少拥有
    org.osgi.service.cm.
    org.osgi.service.metatype.
    的API类,因为这些是SCR运行时所必需的

  • 除非您正在认真定制实际的框架,否则不应该使用
    常量.FRAMEWORK\u SYSTEMPACKAGES
    ,相反,您可能希望使用
    常量.FRAMEWORK\u SYSTEMPACKAGES\u EXTRA
    来扩展框架包导出的内容。(框架实现对于
    framework\u SYSTEMPACKAGES
    有相当好的默认值,在嵌入时通常不需要修改)


我怀疑您尝试获取
ScrService
的第一个块位于嵌入端(即框架外部,而不是安装包内部)

如果是这种情况,那么您有两份
ScrService
——一份从嵌入代码的类加载器加载,另一份在框架解析后由scr包的类加载器加载。这就是为什么您会看到
ClassCastException

您可以只导出SCR捆绑包从框架捆绑包导出的内容

第51页第3.8节指出,在解决线束布线时,如果模块具有相同包的导入和导出定义,则框架将首先尝试外部解决,如果成功,则放弃重叠导出定义

因此,将SCR运行时捆绑包的导出包清单头复制为框架属性:

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();
properties.put(Constants.FRAMEWORK\u SYSTEMPACKAGES\u EXTRA,
“org.ops4j.pax.url.mvn,org.apache.felix.scr;使用:=\”org.osgi.framework,”+
“org.osgi.service.component\”版本=“1.7\”+
“org.apache.felix.scr.component;状态=临时;必需:=状态;”+
“使用:=\”org.osgi.service.component\“;版本=\”1.0\”+
“org.osgi.service.component;使用:=\”org.osgi.framework\“version=”1.2\”;
//你把它交给框架工厂。。。
ServiceLoader=ServiceLoader.load(FrameworkFactory.class);
迭代器迭代器=loader.Iterator();
frameworkframework=iterator.next().newFramework(属性);
framework.start();
有几件事需要注意:

  • 如果您尚未使用
    ConfigurationAdmin
    ,请同时进行安装,以确保您至少拥有
    org.osgi.service.cm.
    org.osgi.service.metatype.
    的API类,因为这些是SCR运行时所必需的

  • 除非您正在认真定制实际的框架,否则不应该使用
    常量.FRAMEWORK\u SYSTEMPACKAGES
    ,相反,您可能希望使用
    常量.FRAMEWORK\u SYSTEMPACKAGES\u EXTRA
    来扩展框架包导出的内容。(框架实现对于
    framework\u SYSTEMPACKAGES
    有相当好的默认值,在嵌入时通常不需要修改)


为了更清楚地了解问题第二部分中导致分辨率错误的原因。。。通过使用FRAMEWORK_SYSTEMPACKAGES,他删除了除org.apache.felix.scr之外的所有系统包导出。所以,再见
org.osgi.framework
。。。再见
javax.*
。。。你明白了。使用FRAMEWORK\u SYSTEMPACKAGES\u EXTRA应该可以解决这个问题。谢谢。你帮了我很多。为了更清楚地说明问题第二部分中导致分辨率错误的原因。。。通过使用FRAMEWORK_SYSTEMPACKAGES,他删除了除org.apache.felix.scr之外的所有系统包导出。所以,再见
org.osgi.framework
。。。再见
javax.*
。。。你明白了。使用FRAMEWORK\u SYSTEMPACKAGES\u EXTRA应该可以解决这个问题。谢谢。你