home personal workZone travel about
code.pst » tech musings and code posts

Posts Tagged ‘eclipse’

Running demo in Eclipse Equinox

Thursday, September 24th, 2009

Running in Eclipse Equinox: Look up basic instructions on equinox quickstart.

Add the following to your config.ini file (note two versions of the same complexapp):


osgi.bundles=javax.servlet_2.4.0.jar@start, services-3.1.2.jar@start, org.eclipse.equinox.http.jar@start, shared-1.0-SNAPSHOT.jar@start, http.handler-1.0-SNAPSHOT.jar@start, complexapp-1.0-SNAPSHOT.jar@start, complexapp-2.0-SNAPSHOT.jar@start

Testing it out: Start Equinox with -console so you have the osgi prompt. Here is a log of commands and interesting portions are highlighted (running on Windows).

rahul@lappy /cygdrive/c/osgidemo/runtime
$ java -jar org.eclipse.osgi_3.5.0.jar -console <-- Start with console

osgi> http.handler started! <-- osgi prompt
New Service added
New Service added

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.5.0.v20090520
1 ACTIVE javax.servlet_2.4.0.v200806031604
2 ACTIVE org.eclipse.osgi.services_3.1.200.v20070605
3 ACTIVE org.eclipse.equinox.http_1.0.300.v20090520-1800
4 ACTIVE com.irahul.shared_1.0.0.SNAPSHOT
5 ACTIVE com.irahul.http.handler_1.0.0.SNAPSHOT
6 ACTIVE com.irahul.complexapp_1.0.0.SNAPSHOT
7 ACTIVE com.irahul.complexapp_2.0.0.SNAPSHOT

osgi> bundle 5
com.irahul.http.handler_1.0.0.SNAPSHOT [5]
Id=5, Status=ACTIVE Data Root=C:\osgidemo\runtime\configuration\org.eclip
se.osgi\bundles\5\data
No registered services.
Services in use: <-- Services used, noticed multiple ComplexService
{com.irahul.shared.ComplexService}={service.id=30}
{org.osgi.service.http.HttpService}={http.port=80, service.pid=org.eclipse.e
quinox.http.HttpService-http, http.address=ALL, service.vendor=IBM, service.desc
ription=OSGi Http Service – IBM Implementation, http.scheme=http, http.timeout=3
0, service.id=26}
{com.irahul.shared.ComplexService}={service.id=29}
No exported packages
Imported packages <-- Pacakages being imported
com.irahul.shared; version=”0.0.0″
javax.servlet; version=”2.4.0″
org.eclipse.equinox.http; version=”0.0.0″ 20090520-1800 [3]>
org.osgi.framework; version=”1.5.0″
org.osgi.service.http; version=”1.2.0″ 070605 [2]>
No fragment bundles
Named class space
com.irahul.http.handler; bundle-version=”1.0.0.SNAPSHOT”[provided]
No required bundles

osgi> bundle 6
com.irahul.complexapp_1.0.0.SNAPSHOT [6]
Id=6, Status=ACTIVE Data Root=C:\osgidemo\runtime\configuration\org.eclip
se.osgi\bundles\6\data
Registered Services
{com.irahul.shared.ComplexService}={service.id=29}
No services in use.
No exported packages
Imported packages
com.irahul.shared
; version=”0.0.0″
org.osgi.framework; version=”1.5.0″
No fragment bundles
Named class space
com.irahul.complexapp; bundle-version=”1.0.0.SNAPSHOT”[provided]
No required bundles

osgi> bundle 7
com.irahul.complexapp_2.0.0.SNAPSHOT [7]
Id=7, Status=ACTIVE Data Root=C:\osgidemo\runtime\configuration\org.eclip
se.osgi\bundles\7\data
Registered Services
{com.irahul.shared.ComplexService}={service.id=30}
No services in use.
No exported packages
Imported packages
com.irahul.shared;
version=”0.0.0″
org.osgi.framework; version=”1.5.0″
No fragment bundles
Named class space
com.irahul.complexapp; bundle-version=”2.0.0.SNAPSHOT”[provided]
No required bundles

osgi> stop 6
Service stopped

osgi> stop 7
Service stopped

osgi> ss

Framework is launched.

id State Bundle
0 ACTIVE org.eclipse.osgi_3.5.0.v20090520
1 ACTIVE javax.servlet_2.4.0.v200806031604
2 ACTIVE org.eclipse.osgi.services_3.1.200.v20070605
3 ACTIVE org.eclipse.equinox.http_1.0.300.v20090520-1800
4 ACTIVE com.irahul.shared_1.0.0.SNAPSHOT
5 ACTIVE com.irahul.http.handler_1.0.0.SNAPSHOT
6 RESOLVED com.irahul.complexapp_1.0.0.SNAPSHOT
7 RESOLVED com.irahul.complexapp_2.0.0.SNAPSHOT

osgi> bundle 5
com.irahul.http.handler_1.0.0.SNAPSHOT [5]
Id=5, Status=ACTIVE Data Root=C:\osgidemo\runtime\configuration\org.eclip
se.osgi\bundles\5\data
No registered services.
Services in use: <-- ComplexService disappear
{org.osgi.service.http.HttpService}={http.port=80, service.pid=org.eclipse.e
quinox.http.HttpService-http, http.address=ALL, service.vendor=IBM, service.desc
ription=OSGi Http Service - IBM Implementation, http.scheme=http, http.timeout=3
0, service.id=26}
No exported packages
Imported packages
com.irahul.shared; version="0.0.0"
javax.servlet; version=”2.4.0″
org.eclipse.equinox.http; version=”0.0.0″ 20090520-1800 [3]>
org.osgi.framework; version=”1.5.0″
org.osgi.service.http; version=”1.2.0″ 070605 [2]>
No fragment bundles
Named class space
com.irahul.http.handler; bundle-version=”1.0.0.SNAPSHOT”[provided]
No required bundles

osgi>

You can access the handler registered at http://localhost. Open it in a browser and hit refresh a few times, you should see a different message as a random service is picked! Then as you stop/start the complexapp bundles you can expect to see different messages.

Next: Spring Dynamic Modules (SpringDM) implementation for this same demo app

Pure Java OSGi demo implementation

Thursday, September 24th, 2009

To interface with OSGi we need a handle to the BundleContext. OSGi provides for an ‘activator’ that is basically the main() method for when a bundle gets started. To create an activator we will implement the BundleActivator interface. The interface has start and stop methods which are invoked at times that their names suggest and you can control the behavior in your implementing class. Then in the Maven plugin (in the POM) add this instruction:

....
<Bundle-Activator>com.irahul.http.handler.Activator</Bundle-Activator>
....

The shared service: The interface for the shared service is one simple method

....
String doSomething();
....

Creating a service implementation: The ComplexService we defined now needs to be implemented and made available as an OSGi service. Here is the Activator:

public class Activator implements BundleActivator{
	public void start(BundleContext context) throws Exception {		
		//register the complex service impl		
		context.registerService("com.irahul.shared.ComplexService",				
				new ComplexService(){
					public String doSomething() {
						return "Hello from Version 1!";
					}			
				}, 
				null);
	}
	.....
}

The service is implemented and registered with the bundle context.

Creating the servlet: This is done by implementing the Servlet interface. The ComplexService does something and the response is sent back to the client. The service to be used is chosen at random in this simple example.

public class MyHandler implements Servlet {
	private List<ComplexService> complexServices = new ArrayList<ComplexService>();
 
	public synchronized void addComplexService(ComplexService service) {
		if(service==null)return;
		complexServices.add(service);
	}
 
	public synchronized void removeComplexService(ComplexService svc) {
		if(svc==null)return;
		complexServices.remove(svc);
	}
 
	public void service(ServletRequest request, ServletResponse response)
		throws ServletException, IOException {
 
		//we may have discovered more than 1 service
		if(complexServices==null|| complexServices.size()==0){
			response.getOutputStream().print("No Service found!");
		}
		else{
			//there are 1...n services, pick one
			//using a random pick
			response.getOutputStream().print(complexServices.get(
					new Random().nextInt(complexServices.size())).doSomething());
		}
	}
 
	....
}

Creating the http handler: The Activator for the HTTP Handler must now get a reference to this service and in turn register itself with the HTTP Server.

In addition to the BundleActivator I am also going to implement the ServiceListener interface. This allows us to get event notifications as services start/stop. We want to dynamically support multiple versions of the ComplexService. The Activator looks like this:

public class Activator implements BundleActivator, ServiceListener{
	private MyHandler myHandler;
	private BundleContext bundleContext;
 
	public void start(BundleContext context) throws Exception {
		//we need this later
		bundleContext = context;
 
		//we are interested in service updates
		context.addServiceListener(this);
 
		//load referenced services		
		//http service to register handler
		ServiceReference svcRef = context.getServiceReference("org.osgi.service.http.HttpService");
		HttpService httpService = (HttpService)context.getService(svcRef);
 
		//create and register http handler (catch all)
		myHandler = new MyHandler();		
		httpService.registerServlet("/", myHandler, null, null);
 
		//get a list of ComplexService (there may be more than 1)
		ServiceReference[] complexSvcRefs = context.getServiceReferences("com.irahul.shared.ComplexService",null);
		if(complexSvcRefs!=null){
			for(ServiceReference ref:complexSvcRefs){
				myHandler.addComplexService((ComplexService)context.getService(ref));
			}
		}
 
		System.err.println("http.handler started!");
	}
	....
	public void serviceChanged(ServiceEvent event) {
		//some service has been registred/removed
		Object svc=bundleContext.getService(event.getServiceReference());
 
		if(svc instanceof ComplexService){
			if(event.getType()==ServiceEvent.REGISTERED){
				System.err.println("New Service added");
				myHandler.addComplexService((ComplexService)svc);
			}
			else{
				System.err.println("Service stopped");
				myHandler.removeComplexService((ComplexService)svc);
			}
		}
	}
}

Download full source.

Next: Running this in Eclipse Equinox