有一种在容器内运行的基于Spring的传统Java应用程序。我试图通过在这个已经存在的应用程序中嵌入Apache Felix来提供一些OSGi插件功能。我通过以下方式声明性地启动框架:
https://dotcms.com/blog/post/navigating-osgi-extending-your-software-to-embed-an-osgi-framework
如果链接不起作用,我正在做的是将Felix作为maven依赖项导入,使用ServiceLoader获取对框架工厂的引用,启动框架,以及加载/启动特定目录中的所有bundle。
该捆绑包是通过Felix Bundle插件创建的,具有以下配置:
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Export-Package>com.example</Export-Package>
<Import-Package>!*</Import-Package>
<Bundle-Name>${project.description}</Bundle-Name>
<Bundle-Activator>com.example.Activator</Bundle-Activator>
<Embed-Transitive>true</Embed-Transitive>
</instructions>
</configuration>
至于依赖:
<dependencies>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
<version>6.0.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
正如您所看到的,它不会导入任何内容(它是整个应用程序中唯一的bundle,servlet本身不是OSGi包)。由于应用程序不是OSGi包,我无法从中导出框架类,因此必须将Felix嵌入到包本身中。
我无法启动捆绑包。这就是我得到的(stacktrace已被编辑了一点):
14:43:52,981 ERROR [con.example.Plugin] (Initialization Thread) Failed to start bundle com.example: org.osgi.framework.BundleException: Activator start error in bundle com.example.Plugin[2].
at org.apache.felix.framework.Felix.activateBundle(Felix.java:2448)
at org.apache.felix.framework.Felix.startBundle(Felix.java:2304)
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:998)
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:984)
Caused by: java.lang.ClassCastException: com.example.Activator cannot be cast to org.osgi.framework.BundleActivator
at org.apache.felix.framework.Felix.createBundleActivator(Felix.java:4744)
at org.apache.felix.framework.Felix.activateBundle(Felix.java:2379)
... 35 more
我已经设法将这个减少到可能的事实,即BundleActivator接口有两个实例:一个在bundle的类加载器中,另一个在Frameworks的ModuleClassLoader中。至少我认为这是正在发生的事情。
人们通常如何解决这个问题?我已经尝试创建另一个捆绑包,只导出要导入的初始捆绑包的框架,但是它在启动时会遇到相同的错误。将spring应用程序重构为整体OSGi能力是不可能的(这就是为什么我使用的是Felix而不是Equinox)。
Bundles不得拥有自己的OSGi Framework类的内部副本(即包org.osgi.framework
及其子包)。他们必须从System Bundle导入这些包。
ClassCastException
的原因是在Java中,类的标识是其完全限定名称和定义它的ClassLoader的组合。如果你在多个ClassLoader中定义BundleActivator
类型 - 当你在bundle中有它的副本时会发生这种情况 - 那么它们被认为是不同的类型。
尝试将依赖框架范围从编译更改为提供