Osgi 通过API创建新的CXF总线

Osgi 通过API创建新的CXF总线,osgi,cxf,Osgi,Cxf,我正在尝试将ApacheCXF与OSGI一起使用。问题在于,我不希望使用cfg.xml文件,而是希望通过API加速我的服务端点。以下就是这样一个例子: InvolvedPartySoap12EndpointImpl involvedPartyServiceImpl = new InvolvedPartySoap12EndpointImpl(); ServerFactoryBean svrFactory = new JaxWsServerFactoryBean(); svr

我正在尝试将ApacheCXF与OSGI一起使用。问题在于,我不希望使用cfg.xml文件,而是希望通过API加速我的服务端点。以下就是这样一个例子:

    InvolvedPartySoap12EndpointImpl involvedPartyServiceImpl = new InvolvedPartySoap12EndpointImpl();
    ServerFactoryBean svrFactory = new JaxWsServerFactoryBean();
    svrFactory.setServiceClass(InvolvedPartyPortType.class);
    svrFactory.setAddress("/bin/InvolvedParty");
    svrFactory.setBus(bus);
    svrFactory.setServiceBean(involvedPartyServiceImpl);
    _server = svrFactory.create();
我面临的问题是为每个OSGI捆绑包创建一个不同的CXF总线,从而允许我在每次激活/停用相应捆绑包时创建/销毁总线。复制以下Karaf命令也是一个目标:

问题是,我没有看到用于创建和销毁CXF总线的API。上面列出的卡拉夫密码在途中似乎不起作用

我认为可以在bundle中创建一个cfg.xml文件来创建总线,但是我没有看到使用给定别名获取总线的API。啊

下面的链接似乎很有希望,但在适应CXFNonSpringServlet的子类时。。。我没有相应的CXF总线,似乎也无法通过API创建:

所以我的问题是。。。有没有人通过OSGI中的API成功地获取、创建和销毁CXF总线(以及相应的servlet)

谢谢,
Randy

您可以实现一个Bundle Activator,在Bundle start/stop上注册/取消注册CXF总线

要创建总线,可以使用BusFactory类。创建的总线必须注册为服务。已注册的服务保存在一个列表中,以便能够在bundle stop上注销它们

下面的例子(也许不太漂亮)应该给你一个想法:

import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
...


public class MyBundleActivator implements BundleActivator {

   private final List<ServiceRegistration> serviceReferences = new ArrayList<>();

   private Bus cxfBus;
   private BundleContext bundleContext;

   @Override
   public void start(BundleContext bundleContext) throws Exception {
      this.bundleContext = bundleContext;
      createAndRegisterCxfBus();
   }

   private void createAndRegisterCxfBus() {
      cxfBus = BusFactory.newInstance().createBus();
      cxfBus.setExtension(MyBundleActivator.class.getClassLoader(), ClassLoader.class);
      registerService(Bus.class.getName(), cxfBus);
   }

   private void registerService(String serviceTypeName, Object service) {
      Dictionary properties = new Properties();
      ServiceRegistration serviceReference = bundleContext.registerService(serviceTypeName, service, properties);
      serviceReferences.add(serviceReference);
   }

   @Override
   public void stop(BundleContext bundleContext) throws Exception {
      unregisterServices();
   }

   private void unregisterServices() {
      for (ServiceRegistration serviceReference : serviceReferences) {
         serviceReference.unregister();
      }
   }
} 

有关更多信息,请参阅。

CXFNonSpringServlet源代码显示此servlet子类根据需要创建CXF总线。因此,我采取的方法是简单地创建CXFNonSpringServlet类的实例,并使用所需的别名向HTTPService注册它

问题是以下代码不能在BundleActivator类中调用,因为不能保证注册servlet所需的HTTPService在bundle激活时存在。为此,我创建了一个带有HTTPService引用的组件,并在组件激活期间注册servlet。我进一步将该组件设置为“即时组件”,以确保在启动期间进行服务注册

@Component(immediate = true)
public class SoapBootstrap
{
    private static final long serialVersionUID = 1L;
    private static final String Alias = "/party";

    private HttpService _httpService;
    private CXFNonSpringServlet _servlet;

    @Reference
    public void setHttpService(HttpService theHttpService)
    {
        try {
            _httpService = theHttpService;
            _servlet = new CXFNonSpringServlet();
            _httpService.registerServlet(Alias, _servlet, null, null);
            registerEndpoints();
        } catch (NamespaceException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ServletException e) {
            e.printStackTrace();
        }
    }

    private void registerEndpoints()
    {
        try {
            XyzSoap12EndpointImpl xyzServiceImpl = new XyzSoap12EndpointImpl();
            ServerFactoryBean svrFactory = new JaxWsServerFactoryBean();
            svrFactory.setServiceClass(XyzPortType.class);
            svrFactory.setAddress("/xyz");
            svrFactory.setBus(_servlet.getBus());
            svrFactory.setServiceBean(xyzServiceImpl);
            svrFactory.create();
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
        }
    }


    @Activate
    void activate(BundleContext context)
    {
    }


    @Deactivate
    void deactivate(BundleContext context)
    {
        _httpService.unregister(Alias);
    }

欢迎建议将此代码移动到Bundle Activator类,但请注意,有必要确保调用Bundle Activator时HTTPService可用。

我实际上尝试过类似的方法,但没有成功。似乎在激活HTTPService和/或CXF捆绑包之前调用BusFactory.newInstance().createBus()会导致新总线自动与“/CXF”别名关联。当以后加载CXF捆绑包时,该代码还会创建一个新捆绑包并将其与“/CXF”别名关联。这会引起冲突。我提出了一种避免重复别名异常的方法,并将在该线程上记录该解决方案。
@Component(immediate = true)
public class SoapBootstrap
{
    private static final long serialVersionUID = 1L;
    private static final String Alias = "/party";

    private HttpService _httpService;
    private CXFNonSpringServlet _servlet;

    @Reference
    public void setHttpService(HttpService theHttpService)
    {
        try {
            _httpService = theHttpService;
            _servlet = new CXFNonSpringServlet();
            _httpService.registerServlet(Alias, _servlet, null, null);
            registerEndpoints();
        } catch (NamespaceException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ServletException e) {
            e.printStackTrace();
        }
    }

    private void registerEndpoints()
    {
        try {
            XyzSoap12EndpointImpl xyzServiceImpl = new XyzSoap12EndpointImpl();
            ServerFactoryBean svrFactory = new JaxWsServerFactoryBean();
            svrFactory.setServiceClass(XyzPortType.class);
            svrFactory.setAddress("/xyz");
            svrFactory.setBus(_servlet.getBus());
            svrFactory.setServiceBean(xyzServiceImpl);
            svrFactory.create();
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
        }
    }


    @Activate
    void activate(BundleContext context)
    {
    }


    @Deactivate
    void deactivate(BundleContext context)
    {
        _httpService.unregister(Alias);
    }