OSGi

OSGi Homepage.

This section describe a proposal, how can you use Crispy in a OSGi envionment (how knopflerfish, oscar or equinox).

Crispy offer two classes. The first class ist the service provider net.sf.crispy.extension.osgi.CrispyActivator. The second class is a example for a client, the service consumer net.sf.crispy.extension.osgi.CrispyClientActivator.

The service provider - CrispyActivator

By the osgi specification describe the META-INF/Manifest.mf the service properties. For example:

Manifest-Version: 1.0
Bundle-Description: Crispy - OSGi extension
Bundle-Name: CrispyActivator
Bundle-Classpath: ., commons-logging.jar, crispy-with-tests-0.6.2.jar, commons-proxy-0.1-SNAPSHOT.jar
Bundle-Activator: net.sf.crispy.extension.osgi.CrispyActivator
Import-Package: org.osgi.framework, net.sf.crispy, net.sf.crispy.impl, test.crispy.example.service
Bundle-Vendor: Crispy
Bundle-SymbolicName: CrispyActivator
Export-Package: test.crispy.example.service, net.sf.crispy.impl, net.sf.crispy
Bundle-Version: 1.0.0

This implementation from the org.osgi.framework.BundleActivator interface, the CrispyActivator, will internal create a instance of the ServiceManager. The ServiceManager can be describe with a property file. The location from this file can be in the META-INF directory or in the same package how the CrispyActivator class, with the name service.properties. For example:

crispy.prop.dynamic.proxy.class=jdk_proxy
crispy.prop.server.url=rmi://localhost:1099
crispy.prop.executor.class=net.sf.crispy.impl.RmiExecutor
test.crispy.example.service.Echo=test.crispy.example.service.EchoImpl
test.crispy.example.service.Calculator=test.crispy.example.service.CalculatorImpl
crispy.osgi.services=test.crispy.example.service.Echo,test.crispy.example.service.Calculator

The source from the CrispyActivator:

public class CrispyActivator implements BundleActivator {

 private static BundleContext bundleContext = null;
	
 public void start(BundleContext pvContext) throws Exception {
  	bundleContext = pvContext;
	URL lvUrl = pvContext.getBundle().getResource("META-INF/service.properties");
	PropertiesLoader lvPropertiesLoader = null;
	// first try to load the properties
	if (lvUrl != null) { 
	  lvPropertiesLoader = new UrlPropertiesLoader(lvUrl); 
	}
	// second try to load the properties
	if (lvPropertiesLoader == null) { 
	  lvPropertiesLoader = new ClassPropertiesLoader(CrispyActivator.class, "service.properties"); 
	}

	Properties lvProperties = lvPropertiesLoader.load();
	ServiceManager lvServiceManager = new ServiceManager(lvProperties);
	createServices(lvProperties, lvServiceManager);
		  
	bundleContext.registerService(IServiceManager.class.getName(), lvServiceManager, new Properties());
 }

 public void stop(BundleContext pvContext) throws Exception {
	bundleContext = null;
 }

 private void createServices(Properties pvProperties, IServiceManager pvServiceManager) throws Exception {
	String lvServiceClassStrings = (String) pvProperties.get("crispy.osgi.services");
	if (lvServiceClassStrings != null) {
	  String lvClassStr[] = lvServiceClassStrings.split(",");
	  for (int i = 0; i < lvClassStr.length; i++) {
	    Class lvServiceClass = Class.forName(lvClassStr[i]);
	    Object lvServiceProxy = pvServiceManager.createService(lvServiceClass);
	    bundleContext.registerService(lvClassStr[i], lvServiceProxy, new Properties());
	  }
	}
 }

The service consumer - CrispyClientActivator

By Client is the description in the META-INF/Manifest.mf too. For example:

Manifest-Version: 1.0
Bundle-Name: CrispyClient
Bundle-ClassPath: ., crispy-with-tests-0.6.2.jar, commons-logging.jar, commons-proxy-0.1-SNAPSHOT.jar
Bundle-Activator: net.sf.crispy.extension.osgi.CrispyClientActivator
Import-Package: org.osgi.framework, test.crispy.example.service
Bundle-SymbolicName: CrispyClient
Bundle-Version: 1.0.0

A possible implementation from the service consumer:

public class CrispyClientActivator implements BundleActivator {

 public void start(BundleContext pvContext) throws Exception {
   // first a echo example
   String filter = "(objectclass=" + Echo.class.getName() + ")";		  
   ServiceReference[] srl =  pvContext.getServiceReferences(null, filter);
   Echo lvEcho = (Echo) pvContext.getService(srl[0]);
   System.out.println("Echo: " + lvEcho.echo("Hello Crispy ..."));
	      
   // second a calculator example
   filter = "(objectclass=" + Calculator.class.getName() + ")";	  
   srl =  pvContext.getServiceReferences(null, filter);
   Calculator lvCalculator = (Calculator) pvContext.getService(srl[0]);
   System.out.println("Add 5.3 + 6.3 = " + lvCalculator.add(5.3, 6.4));      	      
 }

 public void stop(BundleContext pvContext) throws Exception { }

}

Importend:

The Bundle-ClassPath must contain all libraries. In this example can you see the required libraries. The Import-Package part describe the packages from the required services.