PojoSR brings Service Registry to Java
Karl Pauls has released PojoSR 0.1.6, a service registry that enables OSGi bundles to be loaded and services wired together without the need for a full OSGi runtime stack. PojoSR differs from the full OSGi platform in that it does not use nested classloaders; so badly behaved libraries like Hibernate – which are often tripped up in a structured OSGi environment – continue to work as normal.
Unlike running ordinary applications on a classpath, PojoSR can allow you to migrate applications from a flat classpath view into one that is built with μServices. Existing OSGi bundles, such as Declarative Services and the Apache Felix Gogo shell, can be run in a standalone environment. Any JARs on the classpath with Bundle Activators are started, although the bundles are (currently) started in the order that they appear on the classpath. This allows a Java application to start up a OSGi-like runtime in a flat classpath space:
$ curl http://repo1.maven.org/maven2/com/googlecode/pojosr/de.kalpatec.pojosr.framework/0.1.6/de.kalpatec.pojosr.framework-0.1.6.jar > pojosr.jar $ curl http://repo1.maven.org/maven2/org/apache/felix/org.apache.felix.gogo.runtime/0.8.0/org.apache.felix.gogo.runtime-0.8.0.jar > runtime.jar $ curl http://repo1.maven.org/maven2/org/apache/felix/org.apache.felix.gogo.command/0.8.0/org.apache.felix.gogo.command-0.8.0.jar > command.jar $ curl http://repo1.maven.org/maven2/org/apache/felix/org.apache.felix.gogo.shell/0.8.0/org.apache.felix.gogo.shell-0.8.0.jar > shell.jar $ java -cp pojosr.jar:runtime.jar:shell.jar:command.jar de.kalpatec.pojosr.framework.PojoSR g! lb START LEVEL 1 ID|State |Level|Name 0|Active | 1|System Bundle (0.0.1) 1|Active | 1|jar:file:/Library/Java/JavaVirtualMachines/1.6.0_26-b03-383.jdk/Contents/Classes/classes.jar!/ (0.0.0) 2|Active | 1|jar:file:/Library/Java/JavaVirtualMachines/1.6.0_26-b03-383.jdk/Contents/Classes/ui.jar!/ (0.0.0) 3|Active | 1|jar:file:/Library/Java/JavaVirtualMachines/1.6.0_26-b03-383.jdk/Contents/Classes/jsse.jar!/ (0.0.0) 4|Active | 1|jar:file:/Library/Java/JavaVirtualMachines/1.6.0_26-b03-383.jdk/Contents/Home/lib/jce.jar!/ (0.0.0) 5|Active | 1|jar:file:/Library/Java/JavaVirtualMachines/1.6.0_26-b03-383.jdk/Contents/Classes/charsets.jar!/ (0.0.0) 6|Active | 1|jar:file:/System/Library/Java/Extensions/AppleScriptEngine.jar!/ (0.0.0) 7|Active | 1|jar:file:/System/Library/Java/Extensions/dns_sd.jar!/ (0.0.0) 8|Active | 1|jar:file:/System/Library/Java/Extensions/j3daudio.jar!/ (0.0.0) 9|Active | 1|jar:file:/System/Library/Java/Extensions/j3dcore.jar!/ (0.0.0) 10|Active | 1|jar:file:/System/Library/Java/Extensions/j3dutils.jar!/ (0.0.0) 11|Active | 1|jar:file:/System/Library/Java/Extensions/jai_codec.jar!/ (0.0.0) 12|Active | 1|jar:file:/System/Library/Java/Extensions/jai_core.jar!/ (0.0.0) 13|Active | 1|jar:file:/System/Library/Java/Extensions/mlibwrapper_jai.jar!/ (0.0.0) 14|Active | 1|jar:file:/System/Library/Java/Extensions/MRJToolkit.jar!/ (0.0.0) 15|Active | 1|jar:file:/System/Library/Java/Extensions/QTJava.zip!/ (0.0.0) 16|Active | 1|jar:file:/System/Library/Java/Extensions/vecmath.jar!/ (0.0.0) 17|Active | 1|jar:file:/Library/Java/JavaVirtualMachines/1.6.0_26-b03-383.jdk/Contents/Home/lib/ext/apple_provider.jar!/ (0.0.0) 18|Active | 1|jar:file:/Library/Java/JavaVirtualMachines/1.6.0_26-b03-383.jdk/Contents/Home/lib/ext/dnsns.jar!/ (0.0.0) 19|Active | 1|jar:file:/Library/Java/JavaVirtualMachines/1.6.0_26-b03-383.jdk/Contents/Home/lib/ext/localedata.jar!/ (0.0.0) 20|Active | 1|jar:file:/Library/Java/JavaVirtualMachines/1.6.0_26-b03-383.jdk/Contents/Home/lib/ext/sunjce_provider.jar!/ (0.0.0) 21|Active | 1|jar:file:/Library/Java/JavaVirtualMachines/1.6.0_26-b03-383.jdk/Contents/Home/lib/ext/sunpkcs11.jar!/ (0.0.0) 22|Active | 1|Apache Felix Gogo Runtime (0.8.0) 23|Active | 1|Apache Felix Gogo Shell (0.8.0) 24|Active | 1|Apache Felix Gogo Command (0.8.0)
InfoQ caught up with Karl and started off by asking him what PojoSR is all about:
Karl Pauls: Migrating to OSGi requires the code base to not use class loading hacks and statics prevalent in Java (Spring, JPA, etc). Class loading hacks can often be replaced with OSGi services but until now you had to first be clean from a modularity perspective before you could use them.
PojoSR allows applications built in Java to reap the benefits of service-based modularity without first having to rid existing code of any class loader tricks and therefore allows you to migrate to OSGi without first having to clean up all your code. This approach also allows many existing bundles to work out of the box - just by adding them to the class path.
InfoQ: What made you start writing PojoSR?
Karl Pauls: The real starting point was a discussion I had with Peter Kriens at the beginning of 2011. We where discussing that services are actually the most interesting aspect of OSGi and that it is somewhat frustrating to see that a lot of people see OSGi as class loaders on steroids and ignore services completely. As a side effect, they often get frustrated with OSGi since they are trying to solve some of their problems on the wrong layer, which would solve themselves almost naturally when using services.
The main point, however, was that we both saw the OSGi service model really as a new kind of paradigm, like object orientation was 20 years ago. The notion of "dynamic" services and service component models like SCR, iPOJO, etc. are just something that is new and valuable in their own right rather then just something that you have to deal with when you buy into the "dynamic" world of OSGi.
As you can imagine, it was a lively discussion which culminated in me asking what we could do to engage people more on the service level and Peter's idea was that maybe a standalone service registry would help. After thinking about it for a while, it dawned on me that this would actually not be too hard to do since I could just reuse the service registry we have in Apache Felix and that was what I did.
InfoQ: How does the service discovery platform differ in PojoSR and a full OSGi stack?
Karl Pauls: PojoSR provides two ways to work with it. One is as a standalone service registry that captures the service-related methods from the bundle context and allows you to just publish and discover services. This works pretty similarly like it would inside OSGi but it ignores the notion of a bundle almost completely.
The other is that you can add actual bundles on the class path when you start PojoSR and it will execute their activators like a normal OSGi framework would. Neither approach enforces module boundaries, allows for multiple versions of the same package, nor supports most OSGi module-layer features (however, some are supported). For example, it does not support the
Bundle-ClassPath, but it does mimic
Bundle.getResource()so the extender pattern still works.
The main thing it does do is allow you to use services to get rid of class loading hacks over time, after which it will be easier to move to full OSGi and get side-by-side versioning and real module boundaries. Furthermore, it allows you to use bundles in a non-osgi environment.
InfoQ: What have you managed to run successfully using PojoSR?
Karl Pauls: I started rather small and made sure things like the gogo shell and the basic service component models like Declarative Services (SCR), iPOJO, Blueprint, and Dependency Manager work. From there, it was possible to get the Apache Felix Webconsole to work together with the Felix http.jetty Service. Basically, most things I tried to get to work did work in the end with a little bit of tweaking (mostly, making sure all entries on the Bundle-Classpath are extracted and on the real Classpath as well as playing around with the ordering of bundles on the classpath).
I was able to get Vaadin-based stuff to work like the examples Marcel Offermans and me typically use in our tutorials as well as Apache Ace which has a pretty sophisticated Vaadin based shell. Ultimately, even things like Apache Sling work up to a point with maybe the biggest OSGi example being the Eclipse IDE itself.
I can run Eclipse and it works for the normal Java perspective as well as bndtools for example (granted, PDE and P2 don't work since they are heavily bound to equinox). This is not to say that all of these examples work perfectly or that PojoSR could be a complete replacement for their respective OSGi frameworks, but it is showing that a well modularized (OSGi-based) system is likely to work on PojoSR as well (with some tweaking) which obviously, is a testimony to OSGi and modularity. When you write your code modular, you have choice.
InfoQ: Do you think it is likely PojoSR will become a fully-fledged 'OSGi-lite' standard?
Karl Pauls: Well, I cannot and do not speak for the OSGi Alliance in any way, but I do think it would make sense for OSGi to take some position towards this model and hopefully even endorse it by making it some kind of standard. There have been some discussions around that but no final resolution has been reached. I guess the real question is whether this approach gains enough traction to warrant a specification for it or not. I'm fine either way since my main goal of making it easier for people to use services first has been reached just by having the implementation available. I think it can help migrating to OSGi a lot and people are using it today.
InfoQ: What was the reaction like to the JavaOne talk on the Service First Migration to OSGi?
Karl Pauls: At JavaOne we really had two talks about PojoSR. The one was by Richard S. Hall and myself about "μServices for the rest of us" and the other was by BJ Hargrave and Peter Kriens about "Service-First Migration to OSGi". Additionally, I did give a talk and was on a panel at the latest OSGi Community Event in Darmstadt. The feedback that I got from all of this was very positive.
People seem to like the idea especially since it allows them to tackle some of the more common problems when migrating existing applications to OSGi. Another powerful idea to take away is that you can now just put a bundle on the class path that then gets control. That once you run this you do not need to centrally change things because you delegate control to anybody on your class path.
InfoQ: What migration steps are needed to migrate an existing application onto PojoSR?
Karl Pauls: As far as normal Java applications go, there isn't that much to do really. All that is needed is to create an instance of PojoSR somewhere and you are good to go. The jury is still out on how to interact with it in the best way but for now I'd say, the next step is to introduce
Bundle-Activators (or even better, annotation-based service component models) to the application and recast some of its functionality as services. This might be easy or hard depending on your application but the main point is that it doesn't require any other changes.
Furthermore, you might want to start taking advantage of some existing OSGi services and bundles already and just append them to the class path of your application. Let's for example assume you want to get started quickly and just add a plugin system to your application that takes advantage of some API you have already inside your app. That is pretty easily done by just creating a new main method that starts PojoSR first and then the actual application. This way, bundles on the class path can start to interact with your application. If you then for example add a Declarative Services runtime to your class path you can pretty much directly start to use Declarative Services in some of the JARs of your application. Just add the required metadata to your JAR and you are good to go.
InfoQ: Has PojoSR been able to run where a full OSGi stack cannot?
Karl Pauls: Certainly. Peter Kriens used it in his initial blog post as an easy way to get something OSGi-based running on the Amazon AWS Elastic Beanstalk but that was more for convenience as it would be possible to use a full OSGi framework there as well (with quite a bit more work). Maybe the most interesting example was Angelo van der Sijpt and myself getting a demo application together with the Felix Webconsole to work on the Google App Engine (GAE).
That would have been not possible with a full OSGi framework at that point of time [Ed: due to the restrictions on creating threads] but was rather easy to do using PojoSR. Luckily, the places and scenarios where it is hard to use OSGi are getting fewer and fewer but there are still some where it is maybe not impossible but quite some work to integrate a full OSGi runtime – this is where PojoSR might be worthwhile considering as it allows you to develop nicely modular applications according to the OSGi specifications and still run them in a non-OSGi-aware environment. For example, it is trivial to add it to a WAR.
InfoQ: What do you see as the future of PojoSR?
Karl Pauls: I can't give a definitive answer right now. The idea intrigued me and it is interesting to see the uptake. I hope the OSGi Alliance will create a specification for an OSGi framework without the module layer. However, I would like to merge this work back into Apache Felix since it is useful also without standardization. I think PojoSR is really important to get OSGi, and its [service-oriented] architecture, into more applications.
More information about PojoSR can be found from its Google Code project page, and the service itself can be downloaded from either the downloads page or from Maven with mvn:com.googlecode.pojosr:de.kalpatec.pojosr.framework. A pojosr-discuss group is also available. Karl can be contacted at @karlpauls on Twitter.
Tom Gilb & Kai Gilb Jan 26, 2015