Embedding OSGi in Tomcat

My last post embedded OSGi in an application server using Felix, Jetty, and PAX WEB. Here, I’m going to embed Equinox in Tomcat. I originally set out to embed Felix in Tomcat, but the dearth of tools and frameworks available for embedding Felix made using Equinox much easier.

I use the word “much” pretty loosely, though, because there were still some hoops I had to jump through to get JSP compilation working. Of course, PAX WEB provided that capability when embedding Jetty in Felix. Unfortunately, no framework stepped forward that offered these capabilities in this embedding scenario. At least, I wasn’t able to find them.

I want to keep this post strictly educational (like a tutorial), but I’m going to post a follow-up shortly that discusses these two scenarios. To give you something to chew on in the meantime, both scenarios presented a different set of challenges, and we have a long ways to go before many development teams will be able to leverage OSGi for building web applications. Like I said, I’ll explain why in a different post, but for now let’s move on with this example.

Getting Started

In the spirit of using the simplest tools possible, all you’ll need for this example is Tomcat, Ant, and Subversion. If you went through the previous example, you’ve already got Ant and Subversion installed. If you already have Tomcat, you should be set. But if not, download Tomcat 6, which is the version I used for this embedding exercise.

Checkout HelloWorldEmbedJSP

Next, you’ll need to checkout the project from my Google code repository. You can put the project anywhere when checking out, but you’ll have to make sure you know the path relative to each directory so that you can install the necessary bundles. I have the project sitting in a directory right alongside Tomcat. To checkout, open up a Terminal window or DOS prompt and do the following:

svn checkout
http://kcode.googlecode.com/svn/trunk/osgi/HelloWorldEmbedWebJSP

Of course, if you have a Subversion client installed like TortoiseSVN, you can checkout from the directory browser.  I don’t use these tools, though. Next step!

Build the WebApp

This step has nothing whatsoever to do with OSGi. But as a basis for comparision, I felt it would be interesting to package the sample as a web application. Since this is the exact same example I used when embedding Jetty in Felix, it does offer a nice basis for comparing how we can deploy this functionality in different ways. To build the web application, simply navigate to the web directory in the console and type the following:

ant

The build script spits out a web.war file in the bin directory. Simply take this web.war and copy it to the Tomcat webapps directory. If you haven’t started Tomcat yet, you should do so now. Just startup another DOS prompt or console window, navigate to the Tomcat bin directory, and execute the startup.bat or startup.sh. Once this is done, give it a second to explode the web application, and navigate to http://localhost:8080/web/hi. Like I said, if you went through the exercise on my previous post of embedding Jetty in Felix, you’ll see the same thing here deployed as a web application instead of a bundle. Onto OSGi.

The Bridge

The Bridge.war web application is the main reason I chose to use Equinox instead of Felix. It provides two very important functions that are critical when embedding OSGi in an application container. In fact, this is one of the items I’ll be speaking about in my next post – how difficult it is to use OSGi with the current generation of application servers. It’s virtually prohibitive. Anyway, here are the two necessary functions provided by the Bridge.

  • Embeds and launches Equinox
  • Tunnels servlet requests from Tomcat to Equinox

Deploying the Bridge is easy because it’s a webapp. Just take the Bridge.war from the web/lib directory of the HelloWorldEmbedWebJSP project and drop it into the Tomcat webapps directory. Give Tomcat a second to explode the web application, and test it by accessing http://localhost:8080/bridge/sp_test. You should see a page that says the Servlet Delegate is registered. You’ve now got OSGi embedded within Tomcat with a bridge that will feed requests to Tomcat and pass them onto Equinox.

Linux and Mac OS/X users take note. As you’ll recall in the previous examples, we install OSGi bundles from the OSGi console after starting OSGi. Well, since we embedded OSGi in Tomcat, where’s the console? The console is the same console window you used to start Tomcat. But because Tomcat redirects all output to a file, you may not see it. To enable the console, you’ll need to make some changes to the catalina.sh file in the Tomcat bin directory. Windows users shouldn’t have this problem, though I’m sure Windows users are dealing with many other types of problems. Anyway, once you’ve opened catalina.sh, comment out the following line so it looks like this. If you’ve got the same catalina.sh as I do that’s bundled with Tomcat 6, it’s line number 298.

#>> "$CATALINA_BASE"/logs/catalina.out 2>&1 &

Now, restart Tomcat and voila…in the console you used to start Tomcat, you should see the OSGi console. Type ss to see the list of installed bundles. Onward!

Configuring the Environment

Before we deploy the bundle, we need to configure the environment. If we weren’t using JSP, we’d be done. But because JSPs require compilation, and the JSPs will run within Equinox, they can’t use the JSP compiler included with Tomcat. We need to include our own JSP compiler, and we’ll use Jasper. I’ve included all the bundles needed in the same directory where you found Bridge.war. To install the bundles, jump over to the OSGi console, and do the following:

osgi> install file:path to bundle/
javax.servlet.jsp_2.0.0.v200806031607.jar
osgi> install file:path to bundle/
org.apache.commons.el_1.0.0.v200806031608.jar
osgi> install file:path to bundle/
org.apache.commons.logging_1.0.4.v20080605-1930.jar
osgi> install file:path to bundle/
org.apache.jasper_5.5.17.v200806031609.jar
osgi> install file:path to bundle/
org.eclipse.equinox.jsp.jasper_1.0.100.v20080427-0830.jar
osgi> install file:path to bundle/
org.eclipse.equinox.jsp.jasper.registry_1.0.0.v20080427-0830.jar

Now, type ss to view the state of the bundles. If they aren’t active, you’ll need to start each one of them. Again, in the OSGi console, just type:

osgi> start bundle id

Dependening on the dependencies, multiple bundles may start. Just do an ss in between each start to see which ones haven’t been started yet. Wash, Rinse, Repeat!

Build & Deploy the Bundle

Unlike my previous example where I gave you a pre-configured environment that didn’t require you to build anything, we have to do the build and deploy of the bundle ourselves. Why did I do this? Only because Tomcat has a larger footprint than Felix and Jetty, and I didn’t want to put Tomcat in my Google code repository. Building is pretty easy though. We’ve already built and deployed the web application. Building the bundle is done the same way, except we’ll use a different Ant build script. For this step, you can either shut down Tomcat, or open up another DOS or terminal window. Navigate to the HelloWorldEmbedWebJSP/web directory, and type the following:

ant -f buildjar.xml

The JAR file overwrites the web.war in the bin directory and places a valid OSGi bundle named web.jar there for you. To install the bundle, make sure Tomcat is started, and type the following in the OSGi console:

install file:relative path to web.jar/web.jar

The bundle gets installed. Start it up using the OSGi start command. We can now access the OSGi enabled web application by navigating to http://localhost:8080/bridge/hi. Again, it’s the exact same functionality as the other web applications we’ve deployed, except using a different deployment topology.

To shut down, just type close in the OSGi console. We’re done. If you had any problems, let me know via comments here or by contacting me. Next up…some general notes on OSGi and hopefully messing around with Distributed OSGi.

Additional Notes

A few additional notes about this exercise. Obviously it appeared a bit more difficult than embedding Jetty in Felix. But were it not for the PAX WEB framework, that exercise would have proven equally difficult. Also, the Bridge.war performs two very important functions for us. Felix has supporting documentation that shows how to embed Felix, but I found no framework that did it for me. The Bridge.war was available, so I used it. But were a bridge available for Felix, it would be easy to deploy that bridge and install web.jar with Felix embedded within Tomcat.

14 thoughts on “Embedding OSGi in Tomcat

  1. Hello,

    I just doing the tutorial and everything seems fine when I installed all the bundle and starting them. Unfortunately when I try to run http://localhost:8080/bridge/hi, all I get is “HTTP Status 404 – ProxyServlet: /bridge/hi”

    Hope to hear from you..

    Thanks very much…

  2. Hello John,

    Did you check the OSGi console (using ss command) to make sure that all of the bundles are installed, resolved, and active (active is most important)?

  3. Is it possible to start the OSGI container with some application bundles always deployed and started. so ut can be available ready for use without installing these bundles and starting them

  4. Hello Kirk,
    First of all, thank you very much for the blog, it is very usefull for OSGi developers.I`m interested in know how do to deploy equinox into tomcat as you did.I have check out svn project but i don`t find servletbridge.jar code, is it available?
    thanks!

  5. @miguel,

    Are you looking for the source code? Or the servletbridge.jar. The servletbridge.jar is embedded within the bridge.war application. Install the war under Tomcat and look in the lib directory. If you’re looking for the source code, you’ll want to look at the Eclipse Equinox site.

    Here -> http://www.eclipse.org/equinox/server/

    Then look at the HTTP Servlet project. I’m pretty sure that’s the servlet bridge code.

  6. Curious if you know how to pass a port to Equinox for the console.. I saw an example of passing in a command line param if you start Equinox from the command line.. This enabled the console on a telnet port.. Can’t seem to figure out to get it to Equinox when running in the App Server with the Bridge..

    Thanks!

  7. Great tutorial – the only source of this information I could find even now.

    The example works fine, but I have a question – would it be possible to deploy more complex application to tomcat in this way?

    For example I have webapp with context.xml file in WEB-INF directory with realm configured inside – would this work with integrated OSGI, or I will have to rewrite Realm mechanisms to OSGI-way myself?

  8. Hi,

    I am using the servletbridge project and I have a problem about how the servlet can tunnel requests to equinox bundles.

    In fact, it is the eclipse starter called by the frameworklauncher (inside the servletbridge.jar) that installs and starts the bundles.

    I need to transmit information to bundles from the servlet and I don’t know how to do …

Leave a Reply

Your email address will not be published.