logo.pngThis is my third post in the osgi basics series. The topic of today is embedding a servlet container within an osgi container. Of course I am continuing to use felix and now I start using jetty from mortbay. Starting from version 6.1.x, jetty is packaged as a bundle in itself. It is very easy to start a jetty instance within a felix container. Some steps we are going to take in this tutorial:

  1. initialize the container with the required bundles.
  2. Start up the jetty instance with a servlet listening to the default path
  3. Add a servlet that uses a service and takes care of the lifecycle.

Setting up the context

I already talked in my previous post about starting felix and adding bundles to the context. The following block of code shows the bundles that we install after initialization. I install the training service and the sample client. The sample client contains the code to start jetty and install the servlet. Then there are three jars you need to install before you are able to use the jetty instance: jetty, jetty-util and servlet api. Beware, if you want to use jsp’s as well you need to add more jars. Check the following website: embedding jetty.

configMap.put(AutoActivator.AUTO_START_PROP + ".1",
    "file:" + BUNDLE_ROOT + "training-service/1.0-SNAPSHOT/training-service-1.0-SNAPSHOT.jar " +
    "file:" + BUNDLE_ROOT + "example-client/1.0-SNAPSHOT/example-client-1.0-SNAPSHOT.jar " +
    "file:" + JETTY_ROOT + "jetty/6.1.7/jetty-6.1.7.jar " +
    "file:" + JETTY_ROOT + "jetty-util/6.1.7/jetty-util-6.1.7.jar " +
    "file:" + JETTY_ROOT + "servlet-api-2.5/6.1.7/servlet-api-2.5-6.1.7.jar " +
    "file:bundle/slf4j-api-1.4.3.jar " +
    "file:bundle/slf4j-simple-1.4.3.jar " +
    "file:bundle/org.apache.felix.shell-1.0.0.jar " +
    "file:bundle/org.apache.felix.shell.tui-1.0.0.jar ");

Start the jetty instance

jetty_logo.gif
Starting a jetty instance is very easy. The following code shows you how to create a jetty instance while listening to a certain port. Next step is to initialize the context using a context url. In our case we use the root, so you should go to http://localhost:8091/ to have a look at the application. Second step is to add a HelloServlet instance listening to everything in the root path “/*”. The final step before actually starting the jetty instance might be a little less obvious. Here we define an empty servlet returning a non available message. The next step will show why. This servlet will be listening to the url “/trainings”

Server server = new Server(9081);
Context root = new Context(server, JETTY_CONTEXT_PATH, Context.SESSIONS);
root.addServlet(new ServletHolder(new HelloServlet()), MAIN_SERVLET_PATH_SPEC);
servletHolder = new ServletHolder();
servletHolder.setServlet(new NonAvailableServlet());
root.addServlet(servletHolder, TRAININGS_SERVLET_PATH_SPEC);
server.start();

Add training servlet if service is available

We start by registering a service listener that is listening to events related to objects with a name TrainingService :

bundleContext.addServiceListener(this,
    "(&(objectClass=" + TrainingService.class.getName() + "))");

You can add other properties to this query, but for now we do not need that. Since the activator class implements the ServiceListener interface we need to implement the following method. That method receives events that comply to the provided filter.

public void serviceChanged(ServiceEvent event) {
    if (event.getType() == ServiceEvent.REGISTERED) {
        logger.info("Training service is registered");
        servletHolder.setServlet(new TrainingsServlet(
            (TrainingService)bundleContext.getService(event.getServiceReference())));
    } else if (event.getType() == ServiceEvent.UNREGISTERING) {
        logger.info("Training service is unregistered");
        servletHolder.setServlet(new NonAvailableServlet());
    } else if (event.getType() == ServiceEvent.MODIFIED) {
        logger.info("Training service is modified");
        servletHolder.setServlet(new TrainingsServlet(
            (TrainingService)bundleContext.getService(event.getServiceReference())));
    }
}

As you can see from the code there are three type of events we support. We get an event when the service is registered, unregistered or changed. This gives us the opportunity to register the servlet that uses the training service if the service is available and to register the empty servlet when the training service is not available.

You can find the complete source code here (look for the FelixTryout project). and the specific Activator containing the jetty stuff here.

That is about it, hope you liked the article. Use the comments if you have questions. If you would like to read the previous articles, click on them here or click on felix in the tag cloud.
step 1step 2

Embedding Jetty in OSGi (osgi felix sample step 3)
Tagged on:             

2 thoughts on “Embedding Jetty in OSGi (osgi felix sample step 3)

Comments are closed.