"cannot be cast to org.osgi.framework.BundleActivator" 以声明方式启动 OSGi 包时
"cannot be cast to org.osgi.framework.BundleActivator" when declaratively starting OSGi bundle
有这种基于 Spring 的遗留 java 应用程序在容器中运行。我试图通过在这个已经存在的应用程序中嵌入 Apache Felix 来提供一些 OSGi 插件功能。我通过以下方式声明性地启动框架:
https://dotcms.com/blog/post/navigating-osgi-extending-your-software-to-embed-an-osgi-framework
如果 link 不起作用,我正在做的是将 Felix 作为 Maven 依赖项导入,使用 ServiceLoader 获取对框架工厂的引用,启动框架,然后 loading/starting 特定目录中的所有包。
该包是通过 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>
正如您所见,它没有导入任何东西(它是整个应用程序中唯一的包,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 接口有两个实例:一个在包的类加载器中,另一个在框架的 ModuleClassLoader 中。至少我认为这就是正在发生的事情。
人们通常如何解决这个问题?我已经尝试创建另一个包,它只导出要导入的初始包的框架,但是那个包在启动时遇到了同样的错误。将 spring 应用程序重构为整体支持 OSGi 是不可能的(这就是我使用 Felix 而不是 Equinox 的原因)。
Bundle 不得有自己的 OSGi Framework classes 内部副本(即包 org.osgi.framework
及其子包)。他们必须从系统包中导入这些包。
ClassCastException
的原因是在 Java 中 class 的标识是其完全限定名称 和 [=18= 的组合] 定义它的 ClassLoader。如果您在多个 ClassLoader 中定义 BundleActivator
类型——当您在 bundle 中有它的副本时会发生这种情况——那么它们被认为是不同的类型。
尝试将依赖框架范围从 compile 更改为 provided
有这种基于 Spring 的遗留 java 应用程序在容器中运行。我试图通过在这个已经存在的应用程序中嵌入 Apache Felix 来提供一些 OSGi 插件功能。我通过以下方式声明性地启动框架:
https://dotcms.com/blog/post/navigating-osgi-extending-your-software-to-embed-an-osgi-framework
如果 link 不起作用,我正在做的是将 Felix 作为 Maven 依赖项导入,使用 ServiceLoader 获取对框架工厂的引用,启动框架,然后 loading/starting 特定目录中的所有包。
该包是通过 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>
正如您所见,它没有导入任何东西(它是整个应用程序中唯一的包,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 接口有两个实例:一个在包的类加载器中,另一个在框架的 ModuleClassLoader 中。至少我认为这就是正在发生的事情。
人们通常如何解决这个问题?我已经尝试创建另一个包,它只导出要导入的初始包的框架,但是那个包在启动时遇到了同样的错误。将 spring 应用程序重构为整体支持 OSGi 是不可能的(这就是我使用 Felix 而不是 Equinox 的原因)。
Bundle 不得有自己的 OSGi Framework classes 内部副本(即包 org.osgi.framework
及其子包)。他们必须从系统包中导入这些包。
ClassCastException
的原因是在 Java 中 class 的标识是其完全限定名称 和 [=18= 的组合] 定义它的 ClassLoader。如果您在多个 ClassLoader 中定义 BundleActivator
类型——当您在 bundle 中有它的副本时会发生这种情况——那么它们被认为是不同的类型。
尝试将依赖框架范围从 compile 更改为 provided