0

我正在尝试按照 Neil Bartlett 的教程将 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班级从我的应用程序的“捆绑包”文件夹中获取所有捆绑包,然后安装它们并尝试启动它们。

然后我有一个名为的包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;

    }

}

我的斗争来了。如果我实现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. 我也不想发送带有硬编码参数的邮件。

为了避免这些,我在这个包中创建了另一个类:

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 来跟踪我想使用的服务?我应该如何获得正确的捆绑上下文?

提前致谢!

4

0 回答 0