OSGi & Servlets: A Happy Marriage
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!
Update: I updated the code sample to use Declarative Services, as suggested by Jeff and Scott in the comments of this post. After reading this article, please refer to this other post to learn about the changes.
First of all, some preliminary steps. We need to create a new OSGi project and add some dependencies:
- 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).
- 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:
- In the main menu, select Run -> Run Configurations...
- Double click on OSGi Framework in the tree on the left hand side to create a new OSGi-based launch config
- Make sure you select the following eight (8) bundles on the Bundles tab:
- simple.servlet
- javax.servlet
- org.eclipse.equinox.http.jetty
- org.eclipse.equinox.http.servlet
- org.eclispe.osgi
- org.eclispe.osgi.services
- org.mortbay.jetty.server
- org.mortbay.jetty.util
- 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
and name it Simple Servlet (OSGi)
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:
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.
Thanks for reading this post. Follow me on twitter here to be notified about updates and other posts I write. Or, subscribe to my RSS feed here
Trackbacks & Pingbacks
Share your thoughts, post a comment.
Additional comments powered by BackType




Hey Peter, I highly recommend the use of Declarative Services here. That would eliminate ALL of the service tracker code and the vast majority of the OSGi related code (just leaving the HTTP service register and unregister calls). Interested folks might want to look at Chapter 18 in the OSGi and Equinox book (http://equinoxosgi.org) or at the various servlets in the Toast example (http://wiki.eclipse.org/Toast).
More from authorHi Jeff, I will give DS a try and follow up on this. Shouldn’t be a problem as I have the excellent book you mentioned
More from authorJeff, I updated the servlet to use Declarative Services, please see http://www.peterfriese.de/osgi-servlets-flexibility-by-simplicity/ – thanks again for pointing this out.
More from authorHi Peter !
thank you for this insight. I m not too deep into http and jetty inside of equinox. can you give me a point how to deploy a web app (with a web.xml, I have spring http exporters in it) on osgi ?
So long and hoping for the next stammtisch ! Was a nice evening.
More from authorThomas,
More from authorI am not planing on going down the web.xml road any more as long as I can prevent it. The JEE world is dead to me. However, the book Jeff mentioned does contain material on how to embed OSGi apps in traditional web apps and have them deployed to a JEE web server. For your convenience, here a link to the book on Amazon: http://bit.ly/bMa0xa
Hi Peter,
Nice post. One thought: Instead of service tracker you might consider using declarative services…e.g. to inject HttpService into your component (and make the servlet registration even easier). The source code in my amazon cloud image does this, incidently…i.e. one here http://ec2-75-101-228-69.compute-1.amazonaws.com:8080/hello
Actually, if you are game perhaps we can jointly propose and contribute some examples for the eclipsert project. I would be happy to contribute the example that’s out there as well as others.
Also…I hope that you will be able to use the Amazon image in your next post…along with feature-based export and p2 install. I think that would/will make a great follow up post. I’ve been intending to do that myself (since originally making the AMI available) but haven’t been able to do so. If you want/need any assistance in that please just let me know.
Hi Scott,
More from authorI’m definitely planing on using your AMI for my next post – really glad you made it available! Will get back to you regarding this topic by mail.
I’m open for contributing examples to Eclipse RT, let’s discuss this by mail.
Excellent post. Thank you Peter.
More from authorWow, very cool! I’ve actually done something similar, although I used the Spring framework.
More from authorExcellent tutorial Peter!
Thanks, Luis. Glad you like it!
More from authorNew blog post: OSGi & Servlets: A Happy Marriage http://www.peterfriese.de/osgi-servlets-a-happy-marriage/
This comment was originally posted on Twitter
More from authorPeter Friese: OSGi & Servlets: A Happy Marriage http://bit.ly/adW8uH
This comment was originally posted on Twitter
More from authorOSGi basedなサーブレットのメリットって何だろう 「OSGi & Servlets: A Happy Marriage – Peter Friese」 http://bit.ly/biyCfF
This comment was originally posted on Twitter
More from authorServlets in OSGi – http://tinyurl.com/y92sqh4
This comment was originally posted on Twitter
More from authorA simple but good article, it is. RT @lekkim “Servlets in OSGi – http://tinyurl.com/y92sqh4″;
This comment was originally posted on Twitter
More from authorA simple but good article, it is. RT @lekkim “Servlets in OSGi – http://tinyurl.com/y92sqh4″;
This comment was originally posted on Twitter
More from authorOSGi & Servlets: A Happy Marriage – Peter Friese http://bit.ly/aRfxZX
This comment was originally posted on Twitter
More from authorOSGi & Servlets: A Happy Marriage – Peter Friese http://ff.im/-j1FSg
This comment was originally posted on Twitter
More from author@HBehrens done – it’s here: http://bit.ly/dcEMpn
This comment was originally posted on Twitter
More from author