OSGi and Jetty Integration

Introduction

If any OSGi framework based solution needs a servlet container, the OSGified Jetty becomes a good choice. It can be used as the underlying servlet transport provider within an OSGI framework.  This post focus on what are major points to consider when integration Jetty within an OSGi environment.

Integration

The main advantage of Jetty is that it is OSGi framework friendly. It has a set of bundles that can be used for this purpose. Most of the details regarding this bundles is available in the documentation. The  minimum set of bundles needed to embed Jetty in your OSGi environment is given in the documentation.

By default Jetty run-time expects jetty configuration files to be available in a predefined location. This is known as the jetty home. This can be set a a java system variable like below.

-Djetty.home=/opt/custom/jetty

The /opt/custom/jetty will contain the jetty related configuration files under “etc” directory.

The default configuration file of jetty is known as the “jetty.xml”. The other files contains specific configuration. But they also can be merged into one single file as jetty.xml and used.

By default a jetty server instance will be started at port 8080. If this value need to be change then it can be done via setting a system property as below.

-Djetty.port=9763

But in most cases the requirement would be to control on how and when to start a jetty instance in your OSGi environment. So to do that what we can do is to avoid the default jetty instance initialization. If you don’t set the jetty.home system variable, then a default jetty instance will not be started. Then using an OSGi bundle + OSGi Service registartion approach you can boot up a Jetty instance like below.

public class JettyBundleActivator implements BundleActivator {

    @Override
    public void start(BundleContext bundleContext) throws Exception {

        String jettyHome = "/opt/jetty";
        Server server = new Server();
        //server configuration goes here
        String serverName = "jetty-server";
        Dictionary serverProps = new Hashtable();
        serverProps.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, serverName);
        serverProps.put(OSGiServerConstants.JETTY_PORT, "9763");
        serverProps.put(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS,
                        "file:" + jettyHome + File.separator + "jetty.xml");

        //register as an OSGi Service for Jetty to find
        bundleContext.registerService(Server.class.getName(), server, serverProps);
    }
}

The above will register a jetty instance which will be identified by the jetty boot bundle (org.eclipse.jetty.osgi:jetty-osgi-boot) and the instance will be started. By this way, you can take control on the jetty instance boot-up. Like above, any number of jetty instances can be started using the same approach.

The following are the supported features of Jetty in an OSGi environment.

  1. Deploying Bundles as Webapps
  2. Deploying Bundles as Jetty ContextHandlers
  3. Deploying Services as Webapps
  4. Deploying Services as ContextHandlers

Exposing OSGi HttpService

With Jetty integration, the OSGi HttpService can also be exposed for use within the OSGi environment such as servlet registration, etc. An additional bundle is needed in-order to expose HttpService, which includes the HttpService implementation. The equinox http service servlet (HttpServiceServlet) can be used as a HttpService implementation and registered with Jetty for exposing the HttpService. The equinox bundle which can be used for this is org.eclipse.equinox:org.eclipse.equinox.http.servlet.

The below code segment shows the approach on using HttpServiceServlet registration with running Jetty server instance. This code segment can be used within a BundleActivator or a DeclarativeServiceCompoenent.

//exposing the OSGi HttpService by registering the HttpServiceServlet with Jetty.
ServletHolder holder = new ServletHolder(new HttpServiceServlet());
ServletContextHandler httpContext = new ServletContextHandler();

httpContext.addServlet(holder, "/*");
Dictionary servletProps = new Hashtable();
servletProps.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, serverName);

bundleContext.registerService(ContextHandler.class.getName(), httpContext, servletProps);

The above will register HttpServiceServlet with Jetty run-time which will expose the HttpService in the OSGi run-time.

Using OSGi HttpService

By referencing the HttpService, users can register new servlets with it. The jetty run-time will discover and route requests to those servlet request to via HttpServiceServlet.

An example for servlet registration with exposed HttpService is given as below.

@Component(
        name = "HttpServiceComponent",
        description = "This service  component is responsible for retrieving the HttpService " +
                      "OSGi service and register servlets",
        immediate = true
)
public class HttpServiceComponent {

    private static final Logger logger = LoggerFactory.getLogger(HttpServiceComponent.class);

    @Reference(
            name = "http.service",
            referenceInterface = HttpService.class,
            cardinality = ReferenceCardinality.MANDATORY_UNARY,
            policy = ReferencePolicy.STATIC,
            bind = "setHttpService",
            unbind = "unsetHttpService"
    )
    private HttpService httpService;

    @Activate
    protected void start() {
        SampleServlet servlet = new SampleServlet();
        String context = "/sample";
        try {
            logger.info("Registering a sample servlet : {}", context);
            httpService.registerServlet(context, servlet, null,
                                        httpService.createDefaultHttpContext());
        } catch (ServletException | NamespaceException e) {
            logger.error("Error while registering servlet", e);
        }
    }

    protected void setHttpService(HttpService httpService) {
        this.httpService = httpService;
    }

    protected void unsetHttpService(HttpService httpService) {
        this.httpService = null;
    }
}
Advertisements

About kishanthan

I’m currently working as a Software Engineer at WSO2, an open source software company. I hold an Engineering degree, majoring in Computer Science & Engineering field, from University of Moratuwa, Sri Lanka.
This entry was posted in How to, Java, OSGi and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s