Peter Friese is a software engineer with 15+ years hands-on experience in software development, technical writing and public speaking. Peter works as a software engineering consultant at Zühlke Engineering. Having worked on a host of industry projects in diverse domains and being an active committer on a number of open source projects, he has in-depth knowledge in a broad range of technologies. His main areas of expertise are model-driven software development, cross-platform mobile development (iPhone, Android, Windows Phone 7, and mobile web) and Eclipse tooling. Peter blogs at http://www.peterfriese.de and tweets at @peterfriese. Peter is a DZone MVB and is not an employee of DZone and has posted 29 posts at DZone. View Full User Profile

OSGi & Servlets: A Happy Marriage

04.08.2010
| 5895 views |
  • submit to reddit

In this post, I'll show you how to create a simple OSGI-based servlet. Later, we will deploy this servlet to an Amazon EC 2 instance - this should be fun!

First of all, some preliminary steps. We need to create a new OSGi project and add some dependencies:

  1. Create a new plug-in project, naming it simple.servlet. Make sure to select Equinox as the target OSGI framework on the first page of the wizard. Also make sure you've got an activator (that option is on by default).
  2. Open the manifest editor and add the following packages to the Imported Packages section on the Dependencies tab:
    • javax.servlet
    • javax.servlet.http
    • org.osgi.framework
    • org.osgi.service.http
    • org.osgi.util.tracker

Next, let's create the servlet. Servlets are plain Java classes that implement the javax.servlet.Servlet interface. As we want to serve information over HTTP, we can just create a subclass of javax.servlet.http.HttpServlet which already does some of the heavy lifting for us. All we need to do is override the doGet() method. This method does not have a return value. Instead, we need to fill its second parameter, HttpServletResponse resp with the text we want the web browser to display. We could return HTML, but for simplicity's sake, let's just return plain text (so make sure to set the content type to text/plain):

package simple.servlet;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SimpleServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/plain");
resp.getWriter().write("Hello from the cloud!");
}
}

In order for the servlet to be accessible via HTTP, we need to register it. If you have done some JEE/J2EE development, you know that servlets are registered using the web.xml servlet descriptor. As we're not in the JEE world any longer, we can't go down this road. Instead, we will register the servlet using a org.osgi.util.tracker.ServiceTracker. It's a little bit more code to write, but let me tell you: it's worth it as you'll see very soon.

The service tracker will be registered for a specific class - in our case that's org.osgi.service.http.HttpService:

package simple.servlet;

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpService;
import org.osgi.util.tracker.ServiceTracker;

public class HttpServiceTracker extends ServiceTracker {

public HttpServiceTracker(BundleContext context) {
super(context, HttpService.class.getName(), null);
}
// ...

When the service tracker is asked to return the HttpService, we can register our servlet:

  / ...
public Object addingService(ServiceReference reference) {
HttpService httpService = (HttpService) super.addingService(reference);
if (httpService == null)
return null;

try {
System.out.println("Registering servlet at /simple");
httpService.registerServlet("/simple", new SimpleServlet(), null, null);
} catch (Exception e) {
e.printStackTrace();
}

return httpService;
}
/...

Likewise, we must make sure to unregister the servlet when the service tracker is asked to shut down the HttpService

  // ..
public void removedService(ServiceReference reference, Object service) {
HttpService httpService = (HttpService) service;

System.out.println("Unregistering /simple");
httpService.unregister("/simple");

super.removedService(reference, service);
}

}

Now that we've got the servlet in place, we need to make sure the service tracker is started and stopped when our bundle is started and stopped. Those of you familiar with OSGi know where we're heading now: we need to implement the start() and stop() methods of our activator:

package simple.servlet;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class Activator implements BundleActivator {

private HttpServiceTracker serviceTracker;

public void start(BundleContext context) throws Exception {
serviceTracker = new HttpServiceTracker(context);
serviceTracker.open();
}

public void stop(BundleContext context) throws Exception {
serviceTracker.close();
serviceTracker = null;
}

To test your servlet locally, create a new launch config:

  1. In the main menu, select Run -> Run Configurations...
  2. Double click on OSGi Framework in the tree on the left hand side to create a new OSGi-based launch config
  3. and name it Simple Servlet (OSGi)

  4. Make sure you select the following eight (8) bundles on the Bundles tab:
    1. simple.servlet
    2. javax.servlet
    3. org.eclipse.equinox.http.jetty
    4. org.eclipse.equinox.http.servlet
    5. org.eclispe.osgi
    6. org.eclispe.osgi.services
    7. org.mortbay.jetty.server
    8. org.mortbay.jetty.util
  5. Head over to the Arguments tab, making sure the VM arguments text box reads -Declipse.ignoreApp=true -Dosgi.noShutdown=true -Dorg.osgi.service.http.port=8080

You can now start the server by executing the launch config. After a very short time, the text Registering servlet at /simple should appear in the console window, indicating your OSGi-based server and your servlet have been started up (a lot faster that it would have taken on Tomcat or any other JEE server, for that matter).

Open your web browser at http://localhost:8080/simple to observe your servlet in action:

OSGi 
SimpleServlet, local deployment

Congratulations, you've just built your first OSGi-enabled servlet. In the next post, I'll show you how to deploy this servlet in an Amazon EC2 instance. You can download the source code for this post from my SVN repository on Google code.

From http://www.peterfriese.de/osgi-servlets-a-happy-marriage

Published at DZone with permission of Peter Friese, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags: