如何在没有 ClassCastException 的情况下从一个 OSGi 包中公开一个服务
How to expose a service from one OSGi bundle in another without ClassCastException
我已经断断续续地使用 ServiceMix 几年了,但仍然未能成功地在我的包之间共享服务实现——由于使用了代理实现,它总是导致 ClassCastException。
我有两个包和一个嵌入式 jar。
- 嵌入式 jar 包含我的服务 class 实现的接口。
- Bundle 'A' 具有服务 class 实现并导出 impl 所在的包。
Bundle 'B' 导入由 bundle 'A' 公开的包。在 Bundle 'B' 中,以下代码成功获取服务;
IScenarioService scenarioService = null;
try
{
ServiceReference<?>[] servRefs = context.getServiceReferences(IScenarioService.class.getName(), null);
if (servRefs == null || servRefs.length == 0)
{
LOGGER.error("Found no service references for " + IScenarioService.class.getName());
return false;
}
else
{
LOGGER.info("Services: " + servRefs.length);
boolean assign = servRefs[0].isAssignableTo(context.getBundle(), IScenarioService.class.getName());
LOGGER.info("Assign: " + assign);
scenarioService = (IScenarioService) context.getService(servRefs[0]);
}
}
catch (InvalidSyntaxException e)
{
LOGGER.error(e.getMessage());
e.printStackTrace();
return false;
}
我的日志显示找到了 1 项服务并且是服务 'isAssignable',但是在 scenarioService = (IScenarioService) context.getService(servRefs[0]);
行我得到
java.lang.ClassCastException: Proxy511e3d1b_93b7_4de1_835f_3e5df19040b4 cannot be cast to xx.x.xx.IScenarioService
我尝试通过蓝图注入服务,如上代码访问,更改 pom 的 maven-bundle-plugin 中的导入/导出关系以及将所有接口存储在 Bundle 中 'A' 并导出相关包....都无济于事。
有人可以提供一个答案让我摆脱痛苦吗?
谢谢
我假设问题是提供服务的包和使用服务的包看到 class IScenarioService 的不同实例。这通常是由于在两个包中都嵌入了接口或有两个提供接口的包造成的。
避免这种情况的最简单方法是将接口包放在导出包的第三个包中,并在服务提供者和服务消费者包中导入包。
当您使用默认设置时,maven bundle 插件会自动执行此操作。
示例见 this tutorial。模型包包含服务接口,持久性包包含服务提供者,ui 包包含服务消费者。
正如您在代码中看到的那样,maven 包插件仅在父包中设置,几乎不需要在各个包中进行额外的 OSGi 设置。
正如您所看到的,如果您正确地提供和使用服务是非常简单的。
我已经断断续续地使用 ServiceMix 几年了,但仍然未能成功地在我的包之间共享服务实现——由于使用了代理实现,它总是导致 ClassCastException。
我有两个包和一个嵌入式 jar。
- 嵌入式 jar 包含我的服务 class 实现的接口。
- Bundle 'A' 具有服务 class 实现并导出 impl 所在的包。
Bundle 'B' 导入由 bundle 'A' 公开的包。在 Bundle 'B' 中,以下代码成功获取服务;
IScenarioService scenarioService = null; try { ServiceReference<?>[] servRefs = context.getServiceReferences(IScenarioService.class.getName(), null); if (servRefs == null || servRefs.length == 0) { LOGGER.error("Found no service references for " + IScenarioService.class.getName()); return false; } else { LOGGER.info("Services: " + servRefs.length); boolean assign = servRefs[0].isAssignableTo(context.getBundle(), IScenarioService.class.getName()); LOGGER.info("Assign: " + assign); scenarioService = (IScenarioService) context.getService(servRefs[0]); } } catch (InvalidSyntaxException e) { LOGGER.error(e.getMessage()); e.printStackTrace(); return false; }
我的日志显示找到了 1 项服务并且是服务 'isAssignable',但是在 scenarioService = (IScenarioService) context.getService(servRefs[0]);
行我得到
java.lang.ClassCastException: Proxy511e3d1b_93b7_4de1_835f_3e5df19040b4 cannot be cast to xx.x.xx.IScenarioService
我尝试通过蓝图注入服务,如上代码访问,更改 pom 的 maven-bundle-plugin 中的导入/导出关系以及将所有接口存储在 Bundle 中 'A' 并导出相关包....都无济于事。
有人可以提供一个答案让我摆脱痛苦吗? 谢谢
我假设问题是提供服务的包和使用服务的包看到 class IScenarioService 的不同实例。这通常是由于在两个包中都嵌入了接口或有两个提供接口的包造成的。
避免这种情况的最简单方法是将接口包放在导出包的第三个包中,并在服务提供者和服务消费者包中导入包。
当您使用默认设置时,maven bundle 插件会自动执行此操作。
示例见 this tutorial。模型包包含服务接口,持久性包包含服务提供者,ui 包包含服务消费者。
正如您在代码中看到的那样,maven 包插件仅在父包中设置,几乎不需要在各个包中进行额外的 OSGi 设置。
正如您所看到的,如果您正确地提供和使用服务是非常简单的。