Developing Hybrid (OSGi + Java EE) applications in GlassFish
(If you are in a hurry, then download the sample and jump to "build and test" section after doing the necessary set up.)
In my last blog, I mentioned about adding a new module in GlassFish called "OSGi web container for GlassFish." I am glad to say that, it is fully functional now. I have been able to use JSPs, JSFs, Servlets (of course), annotations, resource injection, transactions, EJBs, etc. in a hybrid application (more on hybrid application below). If you noticed, I mentioned EJBs. Although I call it "OSGi web container," since GlassFish now supports "EJB inside war" as standardized by Java EE 6, the new container allows you to use both Web and EJB components in a hybrid application.
What exactly is a hybrid application? I call an application that uses both Java EE & OSGi a hybrid application. Both the technologies have their strengths. While Java EE excels when it comes to security, transaction management, rich component model, persistence, resource pooling, messaging, etc., OSGi brings modularity, dynamism, life cycle management to the table. They make a very powerful combination. Since their combined use is a new development, to make things easier, I shall walk you through the steps of developing and deploying hybrid applications in GlassFish v3.
Setting the stage:
1. Download the latest nightly build of GlassFish v3 and install.
Installation is nothing but unzipping what you downloaded. Builds are promoted once a week. Since this is a work in progress, there may be some important bug fixes that have gone in since last promotion. So, I recommend you use the latest nightly build. After this step, I suggest you ensure installation was successful by starting glassfish. You can start by running:
java -jar glassfishv3/glassfish/modules/glassfish.jar or asadmin start-domain
(You need Java SE 6 to run GlassFish v3)
2. Start embedded JavaDB by running
3. Download "OSGi web container" bundle from here.
Copy the jar file to glassfishv3/glassfish/domains/domain1/autodeploy-bundles/ dir. You can do this while the server is running and the new module will be started automatically. You can see it in the server's output.
As I stated last time, there are two packaging options. In either case, what you develop is a a Web ARchive (WAR file). In one case, it is a plain vanilla war file, where as in the second case, the war file's META-INF/MANIFEST.MF has OSGi meta data in it that makes the war file an OSGi bundle. Let's consider the second case first, because I see that more often used than the first one while writing hybrid applications. From now on, I will refer to such a war as Web Application Bundle (WAB in short).
Download the complete sample from here and unzip it. Those who don't want to build, the final war file is inside hybridapp1/target folder of the zip file. Let's look at the relevant details:
I have used Maven, you are free to use Ant or something else as build tool. The project is laid out as per the default layout of a war project; all the Java classes are in src/main/java, where as web artifacts are in src/main/webapp folder. If you look at the pom.xml, you shall notice that I use maven-war-plugin to package the application as a war file and maven-bundle-plugin to generate the OSGi meta data.
2. Java EE artifacts
The web app contains a couple of servlets, an EJB. It uses Java EE 6 features like @WebServlet to designate a servlet. SO, there is no need for a web.xml. Unfortunately, maven-war-plugin complains if it does not find a web.xml. So, we have an empty web.xml there.
3. Activator.java - the OSGi bundle activator.
A bundle activator is a public class which is instantiated and its start method called when the OSGi bundle is activated (started). So, any application wide initialization can be done here. The reverse happens when the bundle is stopped. In our example, in start method, we lookup a data source using JNDI and create a table in database. In stop method, we drop the table. Important thing to notice is, we are able to use JNDI and JDBC in a bundle activator, which is running outside Java EE context. We will soon talk how the two containers (OSGi container and Java EE container) manage various parts of the same application.
Build and test
Run mvn package to produce target/hybridapp1.war. If you don't have maven, don't worry. The target directory already has the war file. Now copy hybridapp1.war to glassfishv3/glassfish/domains/domain1/autodeploy-bundles/, but while copying rename it to hybridapp1.jar. This is a temporary thing, as there is a bug in the underlying code which does not recognize war files in autodeploy-bundles dir as OSGi bundles. We have a fix, but it has not found its way into a build of GlassFish yet.
That's it. If your server is running, you will see the OSGi bundle getting installed and started as part of which the web application gets deployed. If it is not running, start it for this to happen. You can manage the life cycle of the OSGi bundle by file system commands like cp, rm, touch, etc. See an earlier blog on this. Now that the application is deployed, you can point your browser to
Follow the registration link and then login link. You can see the server.log to see that user name and password got stored in database.
Now, let's delete hybridapp1.jar from autodeploy-bundles folder. As soon as you do that, server's output will show that the bundle got uninstalled and the application got undeployed as well. Now if you try to visit any of the aforementioned URLs, you will get a 404 error.
Relationship between life cycle of OSGi bundle and Java EE Application
Our war file is both a web application as well as an OSGi bundle, which is why it is called a Web Application Bundle. There are two containers involved here, viz: a) OSGi container, which is managing it as an OSGi bundle, b) Java EE container, which is managing it as a web application.
The actual state transition of the bundle looks like this:
The sequence of events is like this:
When you copy the WAB to autodeploy-bundles dir, it first gets installed in OSGi runtime and the framework tries to start it. On the STARTING event, our "OSGi web container" picks it up and deploys it in Java EE runtime after which point OSGi runtime calls the activator's start method and the bundle goes into ACTIVE state.
When you remove the WAB from autodeploy-bundles dir, the bundle gets uninstalled. Of course, uninstall is a superset of stop, so it is stopped first. As part of stopping, the stop method of activator gets called. Once activator.stop returns, STOPPED event is raised and the application gets undeployed from Java EE runtime. Then the OSGi bundle goes into RESOLVED state.
Understanding bundle life cycle and deployment sequence
To have a better understanding of the life cycle and the deployment sequence, let's switch to a more direct mode of operation. Instead of using autodeploy-bundles directory to manage the bundle, let's directly interact with the OSGi runtime. There are two options, viz:
a) we can use Felix shell over telnet protocol,
b) we can use the Felix Web Console.
I will use the former one as I prefer command line tools.
Start glassfish and remove example1.jar from autodeploy-bundles/.
Run these commands (comments are enclosed by ()):
telnet localhost 6666 ps install file:///tmp/hybridapp1/target/hybridapp1.war start
(Now you can see the web application getting deployed. Access the URLs at this point of time.) stop (The web app gets undeployed and URLs are no more accessible.) start (It is back again) uninstall (The bundle gets removed from the system.)
I hope this is sufficient for you to get started. Now, let your imagination take over and let us know how you are able to take advantage of this hybrid approach. In my next article, I show how you can use an EJB as an OSGi service.As always, your feedback is very welcome. Please visit The Aquarium to know the latest news about GlassFish. If you have questions about how to use this feature, please use our forum.