How to consume OSGi service from OSGi HTTP Service

送分小仙女□ 提交于 2019-12-13 06:24:49

问题


I have a bundle A which exposes the following service:

In 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>

Next step, I want to consume this service from a servlet in bundle B.

What I do is the following:

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

As services in OSGi come and go, is it correct to assume that even if the check for non null reference in doPost method passes, the next statement myService.invokeMyServiceMethod() will not throw NPE?

How can I guarantee that I will always get a valid reference to MyService from service registry?

If this is not the correct way of getting service reference from Http Service, what is the correct one?

I am using Equinox as OSGi implementation.

Cheers, Boris


回答1:


I think you've missed a few bits of declarative services (DS) :-) The whole idea of DS that you specify your dependencies in the XML (or MUCH MUCH better with the annotations). This is how the servlet should look like:

@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;
  }
}

The only thing required is to ensure you have Apache Felix's Http Whiteboard bundle installed (yes, it works fine on Equinox, the beauty of standards). This bundle watches any Servlet services being registered and adds them to the Http Service. Since DS ensures that your component is not registered until it has the myService, you myService is guaranteed to be non-null. This is called the DS static mode: all your dependencies are satisfied before you get called.

If you're brave, you could declare the setT method to be dynamic. Then your component would be registered even if there is no T service. E.g. allows you to tell the caller there is no service. This is called the dynamic mode.

The used annotations are standard DS. They are processed by bnd and turned into the XML. This works in maven, gradle, etc. but best of all of course in bndtools.



来源:https://stackoverflow.com/questions/17163093/how-to-consume-osgi-service-from-osgi-http-service

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!