无法在Activator类之外获得BundleContext

时间:2015-05-14 13:48:46

标签: java osgi osgi-bundle embedded-osgi

我想在Neil Bartlett tutorial之后将OSGi嵌入我的应用程序中。我的代码是这样的:

public class OsgiInitServletContextListener implements ServletContextListener {

        @Override
        public void contextInitialized(ServletContextEvent sce) {

            OsgiFramework.initOsgiFramework(sce.getServletContext());

        }

        @Override
        public void contextDestroyed(ServletContextEvent sce) {

            OsgiFramework.destroyOsgiFrameWork();

        }

}

OsgiFramework类是这样的:

public class OsgiFramework {

    private static Framework osgiFramework = null;
    private static BundleContext bundleContext = null;

    public static Framework getOsgiFramework() {
        return osgiFramework;
    }

    public static BundleContext getBundleContext() {
        return bundleContext;
    }

    public static synchronized void initOsgiFramework(ServletContext servletContext) {

        if (osgiFramework == null) {
            Map<String, String> config = new HashMap<String, String>();
            config.put(Constants.FRAMEWORK_STORAGE, "/home/tamasg/osgidata");
            config.put(Constants.FRAMEWORK_STORAGE_CLEAN, "true");
            config.put(
                    Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA,
                    ... /*lot of packages*/);

            try {
                FrameworkFactory frameworkFactory = ServiceLoader.load(FrameworkFactory.class).iterator().next();
                osgiFramework = frameworkFactory.newFramework(config);
                osgiFramework.start();

                bundleContext = osgiFramework.getBundleContext();
                BundleStarter starter = new BundleStarter(servletContext, bundleContext);
                starter.launch();

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

    public static synchronized void destroyOsgiFrameWork() {

        if (OsgiFramework.osgiFramework != null) {
            try {
                OsgiFramework.osgiFramework.stop();
            } catch (BundleException e) {
                e.printStackTrace();
            }
        }
    }
}

我的BundleStarter课程会从我的应用程序&#39;捆绑包中获取所有捆绑包。文件夹,然后安装它们并尝试启动它们。

然后我有一个名为MailSenderService的包,它有一个接口和实现。清单看起来像这样:

Manifest-Version: 1.0
...
Bundle-SymbolicName: 
Bundle-Activator:  com.rr.fr.base.mail.activator.Activator
Bundle-Version: 1.0.7.SNAPSHOT
...
Export-Package: com.rr.fr.base.mail.service;version="1.0.7"
Import-Package: com.fusionr.fnd.zeus.tools.mail,com.fusionr.fnd.zeus.tools.message,com.rr.fr.base.exception,com.rr.fr.base.messages,com.rr.fr.base.persistence,com.rr.fr.base.security,com.rr.fr.base.system,com.rr.fr.base.types,com.rr.fr.interfaces.eb.rms,fusionr.fnd.zeus.springbean,javax.activation,javax.mail;version="[1.4,2)",javax.mail.internet;version="[1.4,2)",javax.mail.util;version="[1.4,2)",org.apache.commons.logging, org.osgi.framework;version="[1.5,2)",org.springframework.context
...

激活器非常简单:

public class Activator implements BundleActivator {
    private ServiceRegistration serviceReg;
    public static BundleContext bc = null;

    @Override
    public void start(BundleContext context) throws Exception {
        bc = context;
        System.out.println(bc.getBundle().getHeaders().get(
Constants.BUNDLE_NAME) + " starting...");
        serviceReg = bc.registerService(
                MailSenderService.class.getName(),
                new FRMailSenderAPI(), null);
        System.out.println("Service registered: MailSenderService");
    }

    @Override
    public void stop(BundleContext context) throws Exception {
        System.out.println(bc.getBundle().getHeaders().get(
Constants.BUNDLE_NAME) + " stopping...");
        bc = null;
        serviceReg.unregister();
        System.out.println("Service stopped: MailSenderService");
    }
}

我认为到目前为止它运作良好。

但是我有另一个试图使用MailSenderService的包。

清单:

Manifest-Version: 1.0
...
Bundle-Activator: com.rr.fr.base.cdfunc.activator.Activator
...
Bundle-ManifestVersion: 2
...
Bundle-ClassPath: .
Import-Package: com.rr.fr.base.barcode,com.rr.fr.base.
 barcode.service,com.rr.fr.base.mail.service,com.rr.fr
 .base.osgi.framework,org.apache.avalon.framework.configuration,org.krys
 alis.barcode4j,org.osgi.framework,org.osgi.util.track
 er

激活剂是这样的:

public class Activator implements BundleActivator {

    private BundleContext bc = null;
    private MailSenderServiceTracker mailSenderST = null;

    @Override
    public void start(BundleContext context) throws Exception {
        this.bc = context;
        System.out.println(bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME) + " starting...");

        mailSenderST = new MailSenderServiceTracker(bc);
        mailSenderST.open();
        System.out.println("The MailSenderServiceTracker is opened.");

    }

    @Override
    public void stop(BundleContext context) throws Exception {
        System.out.println(bc.getBundle().getHeaders().get(Constants.BUNDLE_NAME) + " stopping...");

        mailSenderST.close();
        mailSenderST = null;
        System.out.println("The MailSenderServiceTracker is closed.");

        this.bc = null;

    }

}

这就是我的斗争。 IF 我像这样实施MailSenderServiceTracker

public class MailSenderServiceTracker extends ServiceTracker {

    public MailSenderServiceTracker(BundleContext context) {
        super(context, MailSenderService.class.getName(), null);
    }

    @Override
    public Object addingService(ServiceReference reference) {
        System.out.println("Inside MailSenderServiceTracker.addingService " + reference.getBundle());
        MailSenderService mss = (MailSenderService) context.getService(reference);
        mss.sendMail(parameters...);
        return mss;
    }

    @Override
    public void removedService(ServiceReference reference, Object service) {
        System.out.println("Inside MailSenderServiceTracker.removedService " + reference.getBundle());
        super.removedService(reference, service);
    }
}

这种方式有效,并发送邮件。我的问题是:

  1. 这样代码就会在捆绑活动时运行,这是我不想要的。
  2. 我也不想发送带有硬编码参数的邮件。
  3. 为了避免这些,我在这个包中创建了另一个类:

    public class CashDeskFunction {
    
    
    public void sendCDDataInBarcodeViaEmail(Map<String, Object> data) {
    
            MailSenderServiceTracker mailSenderST = new MailSenderServiceTracker(FrameworkUtil.
        getBundle(MailSenderService.getClass()).
        getBundleContext());
            mailSenderST.open();
            System.out.println("The MailSenderServiceTracker is opened.");
            MailSenderService mailSenderService = (MailSenderService) mailSenderST.getService();
            mailSenderService.sendMail(data);
            mailSenderST.close();
        }
    }
    

    当用户点击按钮时,会调用sendCDDataInBarcodeViaEmail方法。如果我使用这个课程,我当然不会在激活课程中创建mailSenderST。

    我认为我只会跟踪我想要使用的服务,当我想使用它时,但它不会以这种方式工作,因为FrameworkUtil. getBundle(MailSenderService.getClass()). getBundleContext()行给出了null

    关于我做错什么的任何想法? xxxServiceTracker应该如何?我什么时候应该创建一个xxxServiceTracker来跟踪我想要使用的服务?我该如何获得正确的捆绑上下文?

    提前致谢!

0 个答案:

没有答案