Index

OSGI

manifest

minimal manifest:
Bundle-SymbolicName: bundlename
activator
Bundle-Activator: com.example.Activator
import export
Import-Package: org.osgi.framework, java.swing
Export-Package: com.example.foo, com.example.bar
optional osgi entries:
Bundle-Name: human readable name
Bundle-Version: 1.0.0
Bundle-Description: description of bundle
Bundle-Category: optional
Bundle-Vendor: Management Porno ltd.
Bundle-ContactAddress: E.T. phone home
Bundle-Copyright: something something licence
Bundle-DocURL: http://www.example.com/optional/documentation/link

OSGI code samples

Hello World bundle

manifest.mf (minimal):
Bundle-SymbolicName: HelloWorld
Bundle-Activator: Activator
Import-Package: org.osgi.framework
hello world class:
import org.osgi.framework.*;

public class Activator implements BundleActivator {
	public void start(BundleContext context) {
		System.out.println("Hello!");
	}

	public void stop(BundleContext context) {
		System.out.println("Goodbye!");
	}
}
manual packaging
javac -classpath /path/to/felix.jar Activator.java
jar -cfm HelloWorld.jar manifest.mf Activator.class

services

publishing a service
ServiceRegistration<Runnable> registration;
registration = context.registerService(Runnable.class, () -> System.out.println("osgi service"), null);
consuming a service
ServiceTracker<Runnable, Runnable> tracker = new ServiceTracker<>(context, Runnable.class, null);
tracker.open();

Runnable service = tracker.getService();
if (service != null) {
	service.run();
}
adding a service listener
context.addServiceListener(new ServiceListener() {
	@Override
	public void serviceChanged(ServiceEvent event) {
		Map<Integer, String> types = new Hashtable<>();
		types.put(ServiceEvent.REGISTERED, "REGISTERED");
		types.put(ServiceEvent.UNREGISTERING, "UNREGISTERING");
		types.put(ServiceEvent.MODIFIED, "MODIFIED");
		types.put(ServiceEvent.MODIFIED_ENDMATCH, "MODIFIED_ENDMATCH");
		String type = types.get(event.getType());
		System.out.println("service " + type + " detected " + event);
	}
});
listening for services implementing a specified interface
String filter = "(objectclass=" + MyInterface.class.getName() + ")";
context.addServiceListener(listener, filter);
removing the listener (on stop activator)
context.removeServiceListener(listener);

Shutdown OSGI

try {
        Framework systemBundle = context.getBundle(0).adapt(Framework.class);
        systemBundle.stop();
        System.out.println("Waiting up to 2s for OSGi shutdown to complete...");
        systemBundle.waitForStop(2000);

} catch (Exception e) {
        System.err.println("Failed to cleanly shutdown OSGi Framework: " + e.getMessage());
        e.printStackTrace();
}

registering a HTTP Servlet

import java.util.Hashtable;

import javax.servlet.Servlet;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;

public class Activator implements BundleActivator {
	private ServiceRegistration<Servlet> registration;

	@Override
	public void start(BundleContext context) throws Exception {
		Hashtable<String, String> props = new Hashtable<>();
		props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/*");
		registration = context.registerService(Servlet.class, new HelloWorldServlet(), props);
	}

	@Override
	public void stop(BundleContext context) throws Exception {
		registration.unregister();
	}
}
HelloWorldServlet
import java.io.IOException;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloWorldServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.getWriter().println("hello: " + new Date());
		resp.getWriter().close();
	}
}
on felix: requires the HTTP API and HTTP jetty bundles

Registering a servlet Filter

import java.util.Hashtable;

import javax.servlet.Filter;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;

public class Activator implements BundleActivator {
	private ServiceRegistration<Filter> filter;

	@Override
	public void start(BundleContext context) throws Exception {
		Hashtable<String, String> props = new Hashtable<>();
		props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN, "/*");
		filter = context.registerService(Filter.class, new HelloWorldServletFilter(), props);
	}

	@Override
	public void stop(BundleContext context) throws Exception {
		filter.unregister();
	}
}
HelloWorldFilter
import java.io.IOException;
import java.util.Date;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class HelloWorldServletFilter implements Filter {

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		System.out.println("FILTER INIT");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		response.getOutputStream().print("FILTER: " + new Date());
		response.getOutputStream().close();
	}

	@Override
	public void destroy() {
		System.out.println("FILTER EXIT");
	}
}
note: Filters are called only for url's backed by a content provider (servlet) and cannot be used as a catch all.

Further reading

eclipse OSGI support
http://www.vogella.com/tutorials/OSGi/article.html
OSGI specification on HTTP whiteboard
https://osgi.org/specification/osgi.cmpn/7.0.0/service.http.whiteboard.html