Create a whiteboard for JAX-RS applications using Jersey

Git branch: track2

We will use our application server to provide a REST or REST like api on our java domain object model. Jersey is the Reference Implementation for JAX-RS (the Java API for RESTful services). Integrating Jersey in OSGI in relatively straightforward, as all jersey jars have OSGI metadata, and the dependencies are well documented in the jersey user guide.

Matching OSGI modularity with JAX-RS requires some more thought. Most JAX_RS implementation provide runtime classpath scanning to find resource classes. This approach is not viable in OSGI. However the JAX-RS standard also defines the javax.ws.core.Application pseudo abstract class as the only portable means of configuring rest services.
In order to avoid that each bundle needs to configure its Application subclass instance with Jersey, we will use the whiteboard pattern: A bundle that wants to provide rest services just registers an Application service with the OSGI framework, and the whiteboard will pass it to Jersey.
Using Declarative Services the basic whiteboard implementation is easy:

@Component
public class WhiteBoard {	
	private final static String ALIAS = "alias";
	@Reference
	private HttpService httpService;
	
	@Reference(name="zApplication", cardinality=ReferenceCardinality.MULTIPLE, policy=ReferencePolicy.DYNAMIC, 
		target="(&(" + ALIAS + "=/*)(!(" + ALIAS + "=*/)))")
    public void addApplication(Application application, Map properties) throws ServletException, NamespaceException {
    	httpService.registerServlet(getAlias(properties), new ServletContainer(ResourceConfig.forApplication(application)), null, null);
    }

    public void removeApplication(Application application,Map properties) {
    	httpService.unregister(getAlias(properties));
	}
    
    
    private String getAlias(Map properties) {
    	return "/api" + properties.get(ALIAS);
    }    
}
The key part is
	@Reference(name="zApplication", cardinality=ReferenceCardinality.MULTIPLE, policy=ReferencePolicy.DYNAMIC, 
		target="(&(" + ALIAS + "=/*)(!(" + ALIAS + "=*/)))")
	public void addApplication(Application application, Map properties) { 
By specifying both MULTIPLE and DYNAMIC addResource will be called for each Application service, regardless if the service was registered before or after the whiteboard component's activation.
We also take advantage of the fact that Declarative Services will resolve references in alphabetical name order. As such we are sure that the httpService field reference has been set before any addResource is called.
The target filter assures that we have a valid alias property, starting with a / , and not ending with a /

This simple whiteboard works, but we enhanced it with a few features:

We also need to provide the JAX-RS resources access to OSGI services. We need to find some way to bridge Declarative Services with the injection of JAX-RS. When using Jersey we can piggy back on the Jersey's HK2 injector. This can be done by adding an AbstractBinder instance to the Application's getSingletons() set

Finally we need to test our whiteboard. Loading 40 bundles or more to serve a simple Hello Osgi Rest API would be a bit disappointing. On the other hand we do not have yet a lot of interesting information in our app server to build Rest service for. But we do have some 40 bundles, and it would be interesting to see how OSGI wired them together.
Let's see if we can adapt François Zaninotto's dependency wheel from a static view of PHP package dependencies to a dynamic view of OSGI bundle dependencies.
The com.amplifino.nestor.bundles.rest realizes the dependency wheel. It also demonstrates how to use the Http Whiteboard to serve static content. The dependency wheel looks nice, and you can hoover over the edges to focus on a particular bundle, but a dependency graph gives more insight. Unfortunately we did not find a good graph layout program in Java or Javascript, so we used the the dot graph layout program that you need to install separately. The com.amplifino.nestor.dot bundle provides an OSGI service that writes the graph source to the dot's program stdin and reads the generated graph from stdout.
If you only want a quick preview, you can download an executable jar. Start the OSGI server and point your browser at http://localhost:8080/apps/bundles/wheel.html and you should see something like this.
For the dot generated graphs, start at http://localhost:8080/apps/bundles/overview.html and click on any bundle to get a more detailed view of the bundle's wiring showing imported and exported packages and the bundles that import or export them.