gpt4 book ai didi

java - 在 Maven 项目中使用 OSGi 包的 ClassCastException

转载 作者:行者123 更新时间:2023-11-29 05:58:08 24 4
gpt4 key购买 nike

我是 OSGi 的新手,在将 bundle 包含到我的 Maven 项目中时遇到了困难。

我使用 mave-bundle-plugin 创建了一个 API 包和一个实现包。在我的主要项目(Maven 项目)中,我尝试使用 Felix Framework 从 ServiceTracker 获取已实现包的服务。当我最终尝试将获得的服务转换为正确的类型时,我收到了 ClassCastException。

API Maven 项目:

public interface ParserTestService {
String validForStage();
}

API POM:

<artifactId>ParserTest</artifactId>
<version>0.0.2-SNAPSHOT</version>
<packaging>bundle</packaging>

<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${pom.groupId}.${pom.artifactId}</Bundle-SymbolicName>
<Bundle-Vendor>Apache-Felix</Bundle-Vendor>
<Bundle-Version>0.0.1</Bundle-Version>
<Export-Service>de.ParserTestService</Export-Service>
</instructions>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
<version>2.0.4</version>
</dependency>
</dependencies>

实现 Maven 项目:

public class ParserImplService implements ParserTestService {
public String validForStage() {
return "S";
}
}

实现 POM:

<artifactId>ParserTestVersion1</artifactId>
<version>0.0.2-SNAPSHOT</version>
<packaging>bundle</packaging>

<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${pom.groupId}.${pom.artifactId}</Bundle-SymbolicName>
<Bundle-Vendor>Apache-Felix</Bundle-Vendor>
<Bundle-Version>0.0.1</Bundle-Version>
<Bundle-Activator>de.Activator</Bundle-Activator>
<Export-Package>de</Export-Package>
<Export-Service>de.ParserImplService</Export-Service>
<Import-Package>org.osgi.framework</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
<version>2.0.4</version>
<type>bundle</type>
</dependency>
<dependency>
<groupId>de</groupId>
<artifactId>ParserTest</artifactId>
<version>0.0.2-SNAPSHOT</version>
<type>bundle</type>
</dependency>
</dependencies>

Maven 使用以下 list 文件创建了两个 jar 文件:

Manifest-Version: 1.0
Bnd-LastModified: 1340890655296
Build-Jdk: 1.6.0_24
Built-By: br_s1
Bundle-ManifestVersion: 2
Bundle-Name: Parser Test Interface
Bundle-SymbolicName: de.ParserTest
Bundle-Vendor: Apache-Felix
Bundle-Version: 0.0.1
Created-By: Apache Maven Bundle Plugin
Export-Package: de;version="0.0.1"
Export-Service: de.ParserTestService
Tool: Bnd-1.50.0

Manifest-Version: 1.0
Bnd-LastModified: 1340890661890
Build-Jdk: 1.6.0_24
Built-By: br_s1
Bundle-Activator: de.Activator
Bundle-ManifestVersion: 2
Bundle-Name: Parser Test
Bundle-SymbolicName: de.ParserTestVersion1
Bundle-Vendor: Apache-Felix
Bundle-Version: 0.0.1
Created-By: Apache Maven Bundle Plugin
Export-Package: de;version="0.0.1"
Export-Service: de.ParserImplService
Import-Package: org.osgi.framework;version="[1.5,2)"
Tool: Bnd-1.50.0

在我的主要 Maven 项目中,我设置并启动了 Felix 框架。在子文件夹“bundles”中,我复制了上面 Maven 部署过程创建的 jar 文件。在安装例程中,我尝试安装这些包并启动它们:

public class HostActivator implements BundleActivator {
...
public BundleContext getContext()
{
return m_context;
}
...
}

public class HostApplication
{
private HostActivator m_activator = null;
private Felix m_felix = null;
private ServiceTracker m_tracker = null;

public HostApplication()
{
Map<String, Object> configMap = new HashMap<String, Object>();
configMap.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "de.test; version=1.0.0");
m_activator = new HostActivator();
List<BundleActivator> list = new ArrayList<BundleActivator>();
list.add(m_activator);
configMap.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, list);

m_felix = new Felix(configMap);
m_felix.start();

m_tracker = new ServiceTracker(m_activator.getContext(), ParserTestService.class.getName(), null);
m_tracker.open();
}

public void installBundlesFromDir() {

File dir = new File("bundles");
for (File f : dir.listFiles()) {
try {
Bundle b = m_felix.getBundleContext().installBundle("file:"+f.getAbsolutePath());
b.start();

ServiceReference sr = m_felix.getBundleContext().getServiceReference(ParserTestService.class.getName());

ParserTestService service = (ParserTestService) m_felix.getBundleContext().getService(sr);

} catch (BundleException e) {
System.err.println("could not load bundle "+f.getAbsolutePath());
}
}

}
}

对应的POM:

<artifactId>parserUse</artifactId>
<version>0.0.1-SNAPSHOT</version>

<dependencies>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>de</groupId>
<artifactId>ParserTestVersion1</artifactId>
<version>0.0.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>de</groupId>
<artifactId>ParserTest</artifactId>
<version>0.0.2-SNAPSHOT</version>
</dependency>
</dependencies>

但是,当我尝试调用安装例程时,我收到一个 ClassCastException:

java.lang.ClassCastException: de.ParserImplService cannot be cast to de.ParserTestService

我已经检查了类加载器

ParserTestService.class.getClassLoader()

(m_felix.getBundleContext().getService(sr)).getClass().getClassLoader()

它们彼此不同。

我一直认为 OSGi 会为我处理类加载。

有人知道我做错了什么吗?感谢您的帮助!

提前致谢,塞巴斯蒂安

最佳答案

我终于找到了解决这个问题的方法,但只能避免使用 Felix 并改用 Equinox。

1.) API 仅导出包 <Export-Package>de</Export-Package>

2.) Impl 不导出任何内容。它只定义激活器及其导入

<Bundle-Activator>de.Activator</Bundle-Activator>
<Import-Package>org.osgi.framework;de</Import-Package>

3.) 我用 Equinox 替换了整个 HostApplication:

public class HostApplication {
private BundleContext bundleContext;

public HostApplication(String profileName) {
BundleContext bc = null;
Properties frameworkProperties = readCustomProfile(profileName);

frameworkProperties.put("osgi.clean", "true");
frameworkProperties.put("osgi.console", "true");

Map<String, String> frameworkPropertiesMap = new HashMap<String, String>();
for (Object o : frameworkProperties.keySet()) {
frameworkPropertiesMap.put((String) o,
(String) frameworkProperties.getProperty((String) o));
}

EclipseStarter.setInitialProperties(frameworkPropertiesMap);
bc = EclipseStarter.startup(new String[] { "-console", "-dev", "bin" }, null);
}

public boolean containsIegm(String stage, byte[] msg) {

try {
ServiceReference serviceReference = bundleContext.getServiceReference(ParserTest.class.getName());
return ((ParserImplService) bundleContext.getService(serviceReference)).containsIegm(msg);

} catch (Exception ex) {
ex.printStackTrace();
}

return false;
}

public void installBundlesFromDir() {

File dir = new File("bundles");
int i = 0;
for (File f : dir.listFiles()) {
try {
Bundle b = bundleContext.installBundle("file:"+ f.getAbsolutePath());
b.start();
} catch (BundleException e) {
System.err.println("could not load bundle " + f.getAbsolutePath());
}
}

}
}

我通过使用 m_felix 的 BundleContext(参见问题)尝试了与 Felix 完全相同的操作,并完全删除了 HostActivator(我知道这在我的应用程序中没有必要)。但是,我无法让它工作。

无论如何,使用 Equinox,在非 OGSi/非捆绑应用程序中嵌入 OSGi 框架同样容易。

感谢大家的帮助!塞巴斯蒂安

关于java - 在 Maven 项目中使用 OSGi 包的 ClassCastException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11246920/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com