Apache Felix Http Service
This information is only valid for version 2.0.0 and up.
This is an implementation of the Http Service Specification as described in chapter 102 of the OSGi Compendium. The goal is to provide a standard and simplified way to register servlets and resources in a Servlet container, and to associate them with URIs. It also implement a non-standard extension for registering servlet filters as well as a whiteboard implementation. Complete set of features:
- Standard Http Service implementation.
- Extended Http Service implementation that allows for servlet filter registration.
- Run either with Jetty or inside your own application server using the servlet bridge.
- A whiteboard implementation for easy registration of servlets and filters.
- One complete bundle that includes everything to simplify deployment.
Installing
The Apache Felix Http project includes several bundles.
- org.apache.felix.http.jetty - Http Service implementation that is embedding Jetty server.
- org.apache.felix.http.whiteboard - Whiteboard implementation that uses any Http Service implementation.
- org.apache.felix.http.bridge - Http Service implementation that uses the host applicaiton server (bridged mode). Must be used with proxy.
- org.apache.felix.http.bundle - All in one bundle that includes all of the above.
- org.apache.felix.http.proxy - Proxy that is needed inside WAR when deployed inside an application server.
So, in most cases you could just use org.apache.felix.http.bundle and forget about all the other ones.
Using the HttpService
The main components provided by the Apache Felix Http Service bundle are:
HttpService
- Service used to dynamically register resources and servletsHttpContext
- Additional (optional) component to handle authentication, resource and mime type mappings
Servlets created for the OSGi HTTP service don't need to have any reference to the OSGi specification (they only need to conform to the Servlet specification), like in the example:
public class HelloWorld extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().write("Hello World"); } }
To register a Servlet and map it to a URI, you need to retrieve the HttpService
and call its registerServlet
method:
public class Activator implements BundleActivator { public void start(BundleContext context) throws Exception { ServiceReference sRef = context.getServiceReference(HttpService.class.getName()); if (sRef != null) { HttpService service = (HttpService) context.getService(sRef); service.registerServlet("/hello", new HelloWorld(), null, null); } } }
In the same way, you can unregister a Servlet (for instance, in the stop
method of the Bundle Activator) calling the HttpService.unregister
method.
As you notice in the example above, the registerServlet
method accepts four parameters:
- the Servlet alias
- the Servlet instance
- an additional configuration Map
- an HttpContext
The Servlet alias must begin with a slash and must not end with a slash. When a request is processed, the Http Service will try to exact match the requested URI with a registered Servlet. If not existent, it will remove the last '/' in the URI and everything that follows, and try to match the remaining part, and so on.
An additional configuration Map can be optionally specified; if present, all the parameters contained will be copied in the ServletContext object.
Finally, an HttpContext object can be optionally specified to handle authentication, mime type and resource mapping. The HttpContext
interface is quite simple:
public interface HttpContext { String getMimeType(java.lang.String name); //Returns the mime type of the specified resource URL getResource(java.lang.String name); //Returns the URL to retrieve the specified resource boolean handleSecurity(HttpServletRequest request, HttpServletResponse response); //Manages security for the specified request }
The use of a custom HttpContext is typical when you want to serve static contents with the HTTP Service. Let's see first the simplest example of resource registration (without HttpContext
)
public class Activator implements BundleActivator { public void start(BundleContext context) throws Exception { ServiceReference sRef = context.getServiceReference(HttpService.class.getName()); if (sRef != null) { HttpService service = (HttpService) context.getService(sRef); service.registerResources("/static", "/etc/www", null); } } }
As a result of the service.registerResources("/static", "/etc/www", null)
code, all the files available under /etc/www
will be exposed under /static
(f.i. http://localhost:8080/static/001.jpg will render the /etc/www/001.jpg). However, the example above can be simplistic in practice; the HttpContext object is the solution to customize the resource handling.
For instance, you can set the define more complex URI to file mappings overriding the HttpContext.getResource
method, or the correct mime type implementing the method HttpContext.getMimeType
like in the example:
//.... public String getMimeType(String file) { if (file.endsWith(".jpg") { return "image/jpeg"; } else if (file.endsWith(".png")) { return "image/png"; } else { return "text/html"; } } //....
If you implement a customized HttpContext object, don't forget to specify it as third parameter of the registerResources
method invocation:
public class Activator implements BundleActivator { public void start(BundleContext context) throws Exception { ServiceReference sRef = context.getServiceReference(HttpService.class.getName()); if (sRef != null) { HttpService service = (HttpService) context.getService(sRef); HttpContext myHttpContext = new MyHttpContext()); service.registerResources("/static", "/etc/www", myHttpContext); } } }
Using the ExtHttpService
To be able to register filters, it is possible to get hold of org.apache.felix.http.api.ExtHttpService
. This is exported by both jetty and the bridged implementation. Let's see the simplest example of a filter registration.
public class Activator implements BundleActivator { public void start(BundleContext context) throws Exception { ServiceReference sRef = context.getServiceReference(ExtHttpService.class.getName()); if (sRef != null) { ExtHttpService service = (ExtHttpService) context.getService(sRef); service.registerFilter(new HelloWorldFilter(), "/hello/.*", null, 0, null); } } }
Notice the pattern for filters is using regular expressions. So .*
is the same as a simple
using standard servlet patterns.
*
Using the Whiteboard
The whiteboard implementation simplifies the task of registering servlets and filters. A servlet (or filter) can be registered by exporting it as a service. The whiteboard implementation detects all javax.servlet.Servlet
, javax.servlet.Filter
and org.osgi.service.http.HttpContext
services with the right service properties. Let us illustrate the usage by registering a servlet:
public class Activator implements BundleActivator { private ServiceRegistration registration; public void start(BundleContext context) throws Exception { Hashtable props = new Hashtable(); props.put("alias", "/hello"); props.put("init.message", "Hello World!"); this.registration = context.registerService(Servlet.class.getName(), new HelloWorldServlet(), props); } public void stop(BundleContext context) throws Exception { this.registration.unregister(); } }
Servlet service properties:
alias
- Servlet alias to register with.contextId
- Id of context to register with.init.*
- Servlet initialization values.
Filter service properties:
pattern
- Regular expression pattern to register filter with.contextId
- Id of context to register with.service.ranking
- Where in the chain this filter should be placed.init.*
- Filter initialization values.
HttpContext service properties:
contextId
- Id of context to be referenced by a servlet or filter service.
Using the Servlet Bridge
Configuration Properties
The service can both be configured using OSGi environment properties and using Configuration Admin. The service PID for this service is "org.apache.felix.http"
. If you use both methods, Configuration Admin takes precedence. The following properties can be used (some legacy property names still exist but are not documented here on purpose):
org.osgi.service.http.port
- The port used for servlets and resources available via HTTP. The default is80
.org.osgi.service.http.port.secure
- The port used for servlets and resources available via HTTPS. The default is443
.org.apache.felix.http.nio
- Flag to enable the use of NIO instead of traditional IO. One consequence of using NIO with HTTPS is that the bundle needs at least a Java 5 runtime. The default istrue
.org.apache.felix.http.svcprop.port
- The name of the property to use to set the HTTP port. The default isorg.osgi.service.http.port
.org.apache.felix.http.svcprop.port.secure
- The name of the property to use to set the HTTPS port. The default isorg.osgi.service.http.port.secure
.org.apache.felix.http.enable
- Flag to enable the use of HTTP. The default istrue
.org.apache.felix.https.enable
- Flag to enable the user of HTTPS. The default isfalse
.org.apache.felix.https.keystore
- The name of the file containing the keystore.org.apache.felix.https.keystore.password
- The password for the keystore.org.apache.felix.https.keystore.key.password
- The password for the key in the keystore.org.apache.felix.https.truststore
- The name of the file containing the truststore.org.apache.felix.https.truststore.password
- The password for the truststore.org.apache.felix.https.clientcertificate
- Flag to determine if the HTTPS protocol requires, wants or does not use client certificates. Legal values areneeds
,wants
andnone
. The default isnone
.org.apache.felix.http.debug
- Flag to enable debugging for this service implementation. The default isfalse
.
Additionally, the all-in-one bundle uses the following environment properties:
org.apache.felix.http.jettyEnabled
- True to enable jetty as the http container. The default isfalse
.org.apache.felix.http.whiteboardEnabled
- True to enable the whiteboard implementation. The default isfalse
.
Examples
A set of simple examples illustrating the various features are available.
- Filter registration sample: http://svn.apache.org/repos/asf/felix/trunk/http/samples/filter/
- Servlet bridge sample: http://svn.apache.org/repos/asf/felix/trunk/http/samples/bridge/
- Whiteboard sample: http://svn.apache.org/repos/asf/felix/trunk/http/samples/whiteboard/