我有一个包A,它暴露了以下服务:
在OSGI-INF / config.xml
中<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
name="com.example.MyService" modified="updated" immediate="true">
<implementation class="com.example.impl.MyServiceImpl"/>
<service>
<provide interface="com.example.MyService"/>
</service>
</scr:component>
下一步,我想从bundle B中的servlet中使用这个服务。
我所做的是以下内容:
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
BundleContext bundleContext = (BundleContext) getServletContext().getAttribute("osgi-bundlecontext");
if (bundleContext != null) {
// Here MyService is the service exposed as declarative service
MyService myService = getService(bundleContext, MyService.class);
if(myService != null) {
// I want to invoke some method declared in MyService interface
myService.invokeMyServiceMethod();
}
}
}// end of doPost
protected <T> T getService(BundleContext bundleContext, Class<T> type) {
ServiceReference<T> serviceRef = bundleContext.getServiceReference(type);
if (serviceRef == null) {
return null;
}
T service = bundleContext.getService(serviceRef);
return service;
}// end of getService method
随着OSGi中的服务的出现和变化,假设即使在doPost方法中检查非空引用时,下一个语句 myService.invokeMyServiceMethod()也不会抛出NPE,这是正确的吗?
我如何保证始终从服务注册表获取对MyService的有效引用?
如果这不是从Http Service获取服务引用的正确方法,那么正确的方法是什么?
我使用Equinox作为OSGi实现。
干杯, 鲍里斯
答案 0 :(得分:2)
我认为你错过了一些声明性服务(DS):-)你在XML中指定依赖关系的DS的整个想法(或者更好地使用注释)。这就是servlet的样子:
@Component(provide=Servlet.class)
public class MyServlet extends HttpServlet {
T myService;
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
myService.invokeMyServiceMethod();
}
@Reference
T setT(T t) {
myService =t;
}
}
唯一需要的是确保安装了Apache Felix的Http Whiteboard软件包(是的,它在Equinox上运行良好,标准之美)。该捆绑包监视正在注册的任何Servlet服务,并将它们添加到Http服务。由于DS确保您的组件在具有myService之前未注册,因此您的myService保证为非null。这称为DS静态模式:在调用之前,所有依赖项都会得到满足。
如果你很勇敢,你可以声明setT
方法是动态的。然后,即使没有T服务,您的组件也会被注册。例如。允许您告诉来电者没有服务。这称为动态模式。
使用的注释是标准DS。它们由bnd处理并转换为XML。这适用于maven,gradle等,但最重要的是bndtools。