OSGi and Embedded Jetty
There are two approaches to working with OSGi when developing web applications : embedding OSGi into the application server, or embedding the application server into an OSGi runtime. In this post, I’m going to embed Jetty, the application server, into Felix, the OSGi runtime.
As with my previous posts (Simple OSGi Service, OSGi & Modularity, and OSGi & Spring), I’m trying to use the simplest tools for the job to maximize the experience. That means Ant, Felix, Subversion, a simple text editor, and a terminal window. The code can be found in my Google code repository. Look for the project called HelloWorldWebJSP.
As the project name suggests, not only am I going to embed Jetty in Felix, I’m also going to make sure I can serve JSP pages, which requires a bit of extra trickery. If you need additional details, leave a comment or contact me. Let’s go!
Next thing to do is to checkout the project from the google code repository. If you want to use the scripts included with the project to startup Felix, you should checkout the project in a directory right alongside Felix. To checkout the project, you’ll need subversion. Then, navigate to the directory containing Felix and do the following:
For convenience, I checked in the Felix bundle cache, so you don’t need to install all the necessary bundles. The environment is already configured. However, if you’d like to setup the environment yourself, you should be able to delete the felix-cache directory, and after starting Felix, go through the steps of installing the necessary bundles. I’d wait to do this until after you’ve had a chance to step through the rest of the example. But it’s up to you. If something gets messed up, you can always start over with a clean checkout. The bundles you’ll need to install can be found in the /web/lib directory. They are
Next step is to start Felix. Open a terminal window and navigate to the HelloWorldWebJSP directory. You can use the pre-written scripts (assuming your directory structure is correct), or you can invoke it from command-line like the following, replacing the path to felix with the location of felix:
-jar path to felix/felix-1.4.1/bin/felix.jar
Note that you should use the config.properties included with the project, and not the default Felix config.properties. This is because we need to specify an additional package import to make things work (javax.security.cert). Also, if the HelloWorldWebJSP and Felix directories aren’t side-by-side, you’ll have to change the file paths to the Felix bundles in config.properties.
Try it out
At this point, Jetty should be running inside Felix, and you can navigate to the homepage in your browser. To do this, simply point your browser to http://localhost:8380/. Click hello. Click goodbye. To see the JSP, click the link that serves a JSP.
Explore the Configuration
There isn’t a lot of magic here, but it did take some time to find all the bundles necessary to make it happen, especially to get JSP pages working. All in all, there are a total of 10 bundles, and that includes the four Felix bundles, and the bundle we developed as part of the web application (web.jar in ./web/bin directory). To see a list of all the bundles installed, type the following in the terminal window.
Of particular interest, you’ll see two PAX Web bundles. The OPS4J Pax Web - Service (0.5.1) is the bundle that provides Jetty integration (and actually starts Jetty), while OPS4J Pax Web - Jsp Support (0.5.1) provides JSP compilation via Jasper. Note that most of the examples on the PAX Web website use Maven. Since I didn’t want to use Maven, I installed these bundles manually through the Felix console.
Explore the Code
The key element of the web application is the Activator. This registers the servlet, html pages, and JSP page so that Jetty can serve them up. This is where PAX Web makes the job much easier, because it encapsulates integration with Jasper.
There are a few interesting things you can do to experiment a bit further.
First, try setting up the environment yourself. Doing this isn’t that difficult since all of the bundles are included with the project when you checked it out. To do this, close down the existing Felix instance by typing the following in the terminal window.
Next, delete the felix-cache directory. This gives you a clean Felix instance with none of the bundles installed. Startup Felix and then, one-by-one, install the appropriate bundles (listed above) from within felix using the install command, as follows:
install file:./path to bundle
Note that if HelloWorldWebJSP and Felix aren’t sitting side-by-side in the file system, you’ll need to change config.properties to point to the location of the Felix bundles. They are found in the bundle directory under felix. Also, don’t forget to install web.jar from the bin directory (you may have to run the build script), since that’s the JAR that contains our application classes. Then, start the bundles using the following command at the Felix command line in the terminal, where the bundle id is the id of the bundle obtained using the ps command.
start bundle id
Second, make a change to the JSP, html, or servlet. There is an Ant build script in the web directory that allows you to recompile. Depending on what you changed or added, you may have to modify the build script to make sure any new files are included in the JAR file created. Once compiled, redeploy the web.jar to Felix from within the console. You shouldn’t need to restart Felix when doing this. Just do the following, where bundle id is the id of the Hello World Web bundle (ie. the web application):
stop bundle id
update bundle id
refresh bundle id
start bundle id
Third, try deploying another servlet after registering it in the Activator. Or create and deploy another JSP. Or Add some images and additional resources. You can modify the build script to include them in the web.jar that’s already been deployed to Felix, or you can create your own JAR file and deploy it alongside web.jar. You can deploy these changes without interrupting what’s already running within Felix, providing a great feel for the flexibility of OSGi and the adaptable environments possible. Whatever you do, this base install should give you a foundation for experimenting with web applications using OSGi.
Soon I hope, I’ll be experimenting with the alternative configuration - embedding OSGi into the application server.
Update: While the example above uses Felix, I have also tested this example with Equinox. You can follow the same steps and the result is the same. Except the default port for the Equinox solution is 8080, and if you want that changed, you’ll have to do it yourself. Also, when using Equinox, replace the ps command with ss to see the bundle listing.