I’ll leave it to the experts to tell how awesome OSGi is. Among the many benefits, I could tell you why we picked up OSGi for a pet project - Modularity, avoiding JAR hell and dynamic updates (hey, why not?)
We chose Apache Felix (an OSGi framework specification implementation) and Apache Karaf (ummm, how do I put this - something like an app server for OSGi applications). Besides serving as an OSGi container, Karaf has a lot of awesome features (pun intended). And we like the idea of managing multiple Karaf instances managed through Zookeeper.
Enough talk, let’s see some code. This is a rudimentary tutorial on how to run a basic OSGi CXF-JAX Rest Service on Karaf. Given a REST parameter (a name), the service would just return Hello, (name). That’s it !! The entire project could be downloaded here
Please note that this project does not have any domain models and therefore has only two projects - one for the REST (Controller) and the other for the actual service implementation. The project structure looks like this :
Step 1 - Service Implementation
This project just has two ‘useful’ things - the HelloService interface and the HelloServiceImpl class.
Stupid right?
Step 2 - REST project
Similar to the Service project, this project also has just two notable things - the HelloRestService interface and the HelloRestServiceImpl class.
HelloRestService
HelloRestServiceImpl
The HelloRestServiceImpl does nothing but calls the HelloService which gets injected through Blueprint Dependency Injection. Hey, does the inject look very familiar to Spring DI? Exactly !! The Blueprint DI is heavily influenced by Spring DI. In fact, the original work for blueprint is done by Spring.
Step 3 - Injections
XMLs (of any name) inside OSGI-INF/blueprint folder will get picked up for DI scanning.
serviceimpl.xml
Does two things in one tag :
Registers the HelloService into the service registry for lookup
Says that its implementation is HelloServiceImpl
In fact, you could do this in two separate steps. More on that here.
rest.xml
1) cxf-bus is the bus configuration for CXF. It is like the manager for all CXF services. The most common use as far as I know is to configure custom interceptors (for auditing, request/response manipulation, headers manipulation etc)
2) the jaxrs:server initiates a server which would start listening to the URLs that we mapped for. Of course, we would want to map the handlers for the URLs and those go under the serviceBeans.
3) The third note in the XML is the just the restServiceImpl configuration and the injection of the helloService as a property inside the HelloRestServiceImpl
4) The reference tag will lookup the service registry for a bean with the same id.
Step 4 - KAR - Karaf Archive (Optional but easier this way)
Technically, you could just start throwing the bundles generated through the Maven into to the deploy directory of karaf. However, as the project goes big and your dependencies are becoming many, it is advisable to use the .kar archive. Picture .kar as your .war or .ear bundle. A .kar archive, internally, looks something like this :
Building .kar
Building the .kar is composed of two steps :
Step 1
feature.xml
Similar to your web descriptor or application descriptor, we have the features descriptor in Karaf to represent the entire repository that we are bundling together to compose our application.
In our case, we don’t have any external .jar dependencies except for the cxf and the http service for which we are using the in-built features available inside karaf.
Step 2
Maven plugin configuration to create .kar, which indicates where your feature.xml is located (Note that this file is located inside your karaf project)
Wraps
Notice the wrap protocol in front of the mvn protocol in few bundles as in
Not all Jars are OSGi ready but they would obviously be used as a dependency in our project. In those cases, Karaf notices the wrapprotocol and bundles the JAR into an OSGi bundle. In case of doubt, just drop off the wrap and Karaf would complain that the jar is not OSGi compatible. (Alternatively, you could open up each of the dependant jars and check their manifest files)
Changing Log Levels
For all our development environment, we would want to increase our log level to get more feedback from Karaf. This could be achieved by modifying the org.ops4j.pax.logging.cfg file located in your <karaf-installation-directory>/etc
Step 5 - Other Maven configuration
Not technically a step because we would have covered this from the beginning anyway. And nothing fancy here.
Parent pom.xml
Has the rest of the sub-modules configured.
The various library dependencies configured
Rest and ServiceImpl pom.xml
The other poms.xmls aren’t interesting
They just affiliate themselves to the parent pom with the parent tag as in
Step 6 - Bring up Karaf
My Karaf installation is located at : /Users/Gabriel/apps/apache-karaf-2.3.2
Start Karaf :
<installation-dir>/bin/./karaf
Installing CXF and HTTP services
features:chooseurl cxf 2.7.5
features:install http cxf
Checking whether your bundle is installed and your service running
osgi:list
dxf:list-endpoints
Stop Karaf
Ctrl +D (Please note that Ctrl +C closes the connection abruptly instead of stopping Karaf)
In case of accidental Ctrl+C and if Karaf isn’t starting properly, do a
Comments