我想在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);
}
}
这种方式有效,并发送邮件。我的问题是:
为了避免这些,我在这个包中创建了另一个类:
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来跟踪我想要使用的服务?我该如何获得正确的捆绑上下文?
提前致谢!