Wednesday
Feb162011

Starting and configuring a Jetty 7 instance in Equinox 

Starting an embedded Jetty 7 server in Equinox is easy, but getting the right configuration in the right place can be slightly harder.

I am currently using the following Jetty bundles:

org.eclipse.jetty.client
org.eclipse.jetty.continuation
org.eclipse.jetty.deploy
org.eclipse.jetty.http
org.eclipse.jetty.io
org.eclipse.jetty.jmx
org.eclipse.jetty.osgi.boot
org.eclipse.jetty.security
org.eclipse.jetty.server
org.eclipse.jetty.servlet
org.eclipse.jetty.servlets
org.eclipse.jetty.util
org.eclipse.jetty.webapp
org.eclipse.jetty.xml

Some bundles are required only because I want to support gzip loading, jmx introspection and authentication. What bundles can be removed is left as an exercise to the reader.

Jetty is started by the org.eclipse.jetty.osgi.boot bundle, so I make sure this is auto-started. However, in order for Jetty to become useful I also need to reconfigure it.

When the Jetty boot bundle is activated, it runs the DefaultJettyAtJettyHomeHelper#startJettyAtJettyHome(org.osgi.framework.BundleContext) method and that in turn looks at a few properties to determine where to read the configuration from. We elected to use the jetty.home.bundle property.

Armed with the information gleaned from those docs, and the instructions on how to inject new server-wide features into Jetty-OSGi on the eclipse wiki, I created a fragment bundle that is loaded and activated with org.eclipse.jetty.osgi.boot and modifies the jetty.home.bundle property so the configuration is read from the fragment bundle instead of the one included in the Jetty boot bundle.

To set the property I created a fragment activator (all package names have been changed to protect the innocent):

package jettyconfig;

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

public class FragmentActivator implements BundleActivator {

    @Override
    public void start(BundleContext context) throws Exception {
        // Set jetty.home.bundle to the name of our bundle
        System.setProperty("jetty.home.bundle", "jettyconfig");
    }

    @Override
    public void stop(BundleContext context) throws Exception {
    }
}

The fragment activator will be executed just before the Jetty boot bundle is activated.

It would also be possible to set this property from the command-line (as is probably more proper), but after some discussion we preferred to do it like this until something better comes along.

The MANIFEST.MF looks like this:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Jetty Configuration
Bundle-SymbolicName: jettyconfig
Bundle-Version: 1.0.0.qualifier
Fragment-Host: org.eclipse.jetty.osgi.boot;bundle-version="7.2.2"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-Vendor: Henrik Gustafsson

Finally, I could put my config in /etc/jetty.xml in the fragment bundle, and Jetty is started with this configuration. As a starting point for my jetty.xml I used the jetty-osgi-default.xml file and the notes on the jetty.xml wiki page. In particular I needed a ContextHandlerCollection (or perhaps a OSGiAppProvider) configured for Jetty to pick up the services properly.

Friday
Jan282011

Adding authentication to a Jetty 7 deployment through jetty-web.xml

In a setup similar to the one I wrote about here, we had to add some basic http authentication. To add authentication to a context handler all that is needed is to set a security handler to it. This can be accomplished in at least two ways, programmatically or using the web.xml. The former is a bit ugly and the latter stops us from exposing our servlets using OSGi-DS (see previous post). After some internal discussion we opted for a third variant; using jetty-web.xml. I mean, since we had to put it there, so we might as well put it to good use!

From the start we decided we would want to share the authentication configuration between (most of) the different context handlers we have now exposed as OSGi-services. This means we needed some way of sharing the data that we create. We have the realm file used by the HashLoginService configurable as a system property, and we could share that, creating new HashLoginService instances in each context handler. However, it gets more complicated if we want to configure some other LoginService and use that everywhere. So, we decided to attempt to share the actual LoginService instance. In fact, after some experimentation and refactoring of the xml-files I ended up with being able to share the entire SecurityHandler between the services using Server#setAttribute().

This resulted in the following addition to our jetty.xml:

<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN"
    "http://www.eclipse.org/jetty/configure.dtd">

<Configure id="Server" class="org.eclipse.jetty.server.Server">

    <!-- old stuff here -->

    <New class="org.eclipse.jetty.security.HashLoginService"
        id="DefaultLoginService">
        <Set name="name">MyRealm</Set>
        <Set name="config">
            <SystemProperty name="jetty.authrealm"
                default="/etc/webthing/realm.properties" />
        </Set>
        <Set name="refreshInterval">5</Set>
        <Call name="start"/>
    </New>

    <New class="org.eclipse.jetty.http.security.Constraint"
        id="DefaultSecurityConstraint">
        <Set name="authenticate">true</Set>
        <Set name="name">BASIC</Set>
        <Set name="roles">
            <Array type="java.lang.String">
                <Item>admin</Item>
            </Array>
        </Set>
    </New>

    <New class="org.eclipse.jetty.security.ConstraintSecurityHandler"
        id="DefaultSecurityHandler">
        <Set name="loginService">
            <Ref id="DefaultLoginService" />
        </Set>
        <Set name="realmName">MyRealm</Set>
        <Call name="addConstraintMapping">
            <Arg>
                <New class="org.eclipse.jetty.security.ConstraintMapping">
                    <Set name="pathSpec">/*</Set>
                    <Set name="constraint">
                        <Ref id="DefaultSecurityConstraint" />
                    </Set>
                </New>
            </Arg>
        </Call>
    </New>

    <Call name="addBean">
        <Arg><Ref id="DefaultLoginService" /></Arg>
    </Call>

    <Call name="setAttribute">
        <Arg>DefaultSecurityConstraint</Arg>
        <Arg><Ref id="DefaultSecurityConstraint" /></Arg>
    </Call>

    <Call name="setAttribute">
        <Arg>DefaultLoginService</Arg>
        <Arg><Ref id="DefaultLoginService" /></Arg>
    </Call>

    <Call name="setAttribute">
        <Arg>DefaultSecurityHandler</Arg>
        <Arg><Ref id="DefaultSecurityHandler" /></Arg>
    </Call>

</Configure>

Notice how we set attributes on the server for several of the objects we created. We can't/don't want to reuse the same SecurityHandler everywhere (actually not, read to the end...), but we still want to reuse some of the other parts. This allows us to change some of the settings, but still lets us reconfigure the LoginService from a single place.

Next, I just had to swap the otherwise empty jetty-web.xml for this this:

<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN"
    "http://www.eclipse.org/jetty/configure.dtd">

<Configure class="test.webthing.WebThing">
    <Property name="Server">
        <Call name="getAttribute" id="DefaultSecurityHandler">
            <Arg>DefaultSecurityHandler</Arg>
        </Call>
    </Property>
    <Set name="securityHandler">
        <Ref id="DefaultSecurityHandler" />
    </Set>
</Configure>

Yea, right. Finally. However, once a second component is added, this thing reared its head:

2011-01-31 12:51:11,173 INFO  org.eclipse.jetty.util.log Deployable added: webthing-1.0.0.qualifier/jetty-web.xml
2011-01-31 12:51:11,206 WARN  org.eclipse.jetty.util.log FAILED t.w.WebThing{/hello,null}: java.lang.IllegalStateException: STARTED
2011-01-31 12:51:11,206 WARN  org.eclipse.jetty.util.log Unable to reach node goal: started
java.lang.IllegalStateException: STARTED
    at org.eclipse.jetty.server.handler.HandlerWrapper.setHandler(HandlerWrapper.java:70)
    at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:205)
    at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:584)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:55)
    at org.eclipse.jetty.deploy.bindings.StandardStarter.processBinding(StandardStarter.java:36)
    at org.eclipse.jetty.deploy.AppLifeCycle.runBindings(AppLifeCycle.java:180)
    at org.eclipse.jetty.deploy.DeploymentManager.requestAppGoal(DeploymentManager.java:481)
    at org.eclipse.jetty.deploy.DeploymentManager.addApp(DeploymentManager.java:137)
    at org.eclipse.jetty.osgi.boot.OSGiAppProvider.addContext(OSGiAppProvider.java:197)
    at org.eclipse.jetty.osgi.boot.OSGiAppProvider.addContext(OSGiAppProvider.java:179)
    at org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleDeployerHelper.registerContext(WebBundleDeployerHelper.java:400)
    at org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleDeployerHelper.registerContext(WebBundleDeployerHelper.java:348)
    at org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleDeployerHelper.registerContext(WebBundleDeployerHelper.java:308)
    at org.eclipse.jetty.osgi.boot.internal.webapp.JettyContextHandlerServiceTracker.serviceChanged(JettyContextHandlerServiceTracker.java:247)
    at org.eclipse.osgi.internal.serviceregistry.FilteredServiceListener.serviceChanged(FilteredServiceListener.java:104)
    at org.eclipse.osgi.framework.internal.core.BundleContextImpl.dispatchEvent(BundleContextImpl.java:933)
    at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:227)
    at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:149)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEventPrivileged(ServiceRegistry.java:756)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEvent(ServiceRegistry.java:711)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.register(ServiceRegistrationImpl.java:130)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.registerService(ServiceRegistry.java:206)
    at org.eclipse.osgi.framework.internal.core.BundleContextImpl.registerService(BundleContextImpl.java:507)
    at org.eclipse.equinox.internal.ds.InstanceProcess.registerService(InstanceProcess.java:504)
    at org.eclipse.equinox.internal.ds.InstanceProcess.buildComponents(InstanceProcess.java:212)
    at org.eclipse.equinox.internal.ds.Resolver.buildNewlySatisfied(Resolver.java:441)
    at org.eclipse.equinox.internal.ds.Resolver.enableComponents(Resolver.java:213)
    at org.eclipse.equinox.internal.ds.SCRManager.performWork(SCRManager.java:800)
    at org.eclipse.equinox.internal.ds.SCRManager$QueuedJob.dispatch(SCRManager.java:767)
    at org.eclipse.equinox.internal.ds.WorkThread.run(WorkThread.java:89)
    at org.eclipse.equinox.internal.util.impl.tpt.threadpool.Executor.run(Executor.java:70)

Turns out it's not a particularly good idea to share the security handler. So, in the end the configuration for the components looked like this:

<?xml version="1.0"  encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN"
    "http://www.eclipse.org/jetty/configure.dtd">

<Configure class="test.webthing.WebThing">
    <Property name="Server">
        <Call name="getAttribute" id="DefaultLoginService">
            <Arg>DefaultLoginService</Arg>
        </Call>
        <Call name="getAttribute" id="DefaultSecurityConstraint">
            <Arg>DefaultSecurityConstraint</Arg>
        </Call>
    </Property>

    <Set name="securityHandler">
        <New class="org.eclipse.jetty.security.ConstraintSecurityHandler">
            <Set name="loginService">
                <Ref id="DefaultLoginService" />
            </Set>
            <Set name="realmName">MyRealm</Set>
            <Call name="addConstraintMapping">
                <Arg>
                    <New class="org.eclipse.jetty.security.ConstraintMapping">
                        <Set name="pathSpec">/*</Set>
                        <Set name="constraint">
                            <Ref id="DefaultSecurityConstraint" />
                        </Set>
                    </New>
                </Arg>
            </Call>
        </New>
    </Set>
</Configure>

Now, if there were only some nice way of injecting these services into our OSGi-components without going though the Server attributes...

Improvement suggestions and corrections welcome!

Wednesday
Jan262011

Deploying a servlet in Jetty 7 using OSGi-DS 

I recently had to deploy a servlet to an instance of a Jetty 7 (7.2.2 to be precise) server embedded in Equinox. To bootstrap Jetty I used the org.eclipse.jetty.osgi.boot bundle as described on the Eclipse Wiki. This bundle is not shipped with 7.2.2 but can be built from source easily.

As it stands, all services in our system runs using OSGi-DS, and I figured it would be neat if I were able to deploy the servlets in a similar fashion.

The servlets themselves are constructed in a non-trivial manner, and had some dependencies on other OSGi-DS-exposed services, so programmatic construction of the servlet instances is preferable for now.

Turns out that's not completely simple or free of hacks, but also not extremely hard.

The org.eclipse.jetty.osgi.boot bundle registers a service tracker looking for services extending org.eclipse.jetty.server.handler.ContextHandler, which basically means that if I just add a <provide interface="org.eclipse.jetty.server.handler.ContextHandler"/> tag to my OSGi service component description I can have Jetty pick up on that automagically.

Yay! Well, almost. This was my first try at a component:

package test.webthing;

import java.util.Map;

import javax.servlet.Servlet;

import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.osgi.service.component.ComponentContext;

public class WebThing extends ServletContextHandler {

    public WebThing() {
        setContextPath("/hello");
    }

    private void addServlet(final Servlet servlet) {
        final ServletHolder holder =
            getServletHandler().newServletHolder();
        holder.setServlet(servlet);
        addServlet(holder, "/");
    }

    public void activate(Map<String, Object> properties)
        throws Exception {
        addServlet(new HelloServlet());
    }
}

That didn't quite work, however; I got this beauty in the logs:

2011-01-26 23:04:24,302 DEBUG org.eclipse.jetty.osgi.boot FrameworkEvent ERROR
java.lang.IllegalArgumentException: the property contextFilePath is required
    at org.eclipse.jetty.osgi.boot.internal.webapp.JettyContextHandlerServiceTracker.serviceChanged(JettyContextHandlerServiceTracker.java:231)
    at org.eclipse.osgi.internal.serviceregistry.FilteredServiceListener.serviceChanged(FilteredServiceListener.java:104)
    at org.eclipse.osgi.framework.internal.core.BundleContextImpl.dispatchEvent(BundleContextImpl.java:933)
    at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:227)
    at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:149)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEventPrivileged(ServiceRegistry.java:756)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEvent(ServiceRegistry.java:711)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.register(ServiceRegistrationImpl.java:130)
    at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.registerService(ServiceRegistry.java:206)
    at org.eclipse.osgi.framework.internal.core.BundleContextImpl.registerService(BundleContextImpl.java:507)
    at org.eclipse.equinox.internal.ds.InstanceProcess.registerService(InstanceProcess.java:504)
    at org.eclipse.equinox.internal.ds.InstanceProcess.buildComponents(InstanceProcess.java:212)
    at org.eclipse.equinox.internal.ds.Resolver.buildNewlySatisfied(Resolver.java:441)
    at org.eclipse.equinox.internal.ds.Resolver.enableComponents(Resolver.java:213)
    at org.eclipse.equinox.internal.ds.SCRManager.performWork(SCRManager.java:800)
    at org.eclipse.equinox.internal.ds.SCRManager$QueuedJob.dispatch(SCRManager.java:767)
    at org.eclipse.equinox.internal.ds.WorkThread.run(WorkThread.java:89)
    at org.eclipse.equinox.internal.util.impl.tpt.threadpool.Executor.run(Executor.java:70)

Ok, so, I set my breakpoints to stun and started debugging. What happened was that in JettyContextHandlerServiceTracker#serviceChanged() there was a check that required the property "contextFilePath" of the service to be set to something other than null. Digging further revealed that not only did it have to be set to something non-null, it also needed to be a valid jetty-web.xml-file. "But Why!?", I exclaimed, but added the property to my component properties and created a dummy jetty-web.xml file:

<?xml version="1.0"  encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC
  "-//Jetty//Configure//EN"
  "http://www.eclipse.org/jetty/configure.dtd">

<Configure class="test.webthing.WebThing" />

Aha! Progress in the logs!

2011-01-26 22:36:35,763 INFO  org.eclipse.jetty.util.log Deployable added: webthing-1.0.0.qualifier/jetty-web.xml

And indeed, the servlet works!

$ curl http://localhost:8080/hello/
HELLO
$

So I modified my component slightly to look like this:

package test.webthing;

import java.util.Map;

import javax.servlet.Servlet;

import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

public class WebThing extends ServletContextHandler {
    private void addServlet(final Servlet servlet) {
        final ServletHolder holder =
            getServletHandler().newServletHolder();
        holder.setServlet(servlet);
        addServlet(holder, "/");
    }

    public void activate(Map<String, Object> properties)
        throws Exception {
        setContextPath(
            (String) properties.get(
                OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH));
        addServlet(new HelloServlet());
    }
}

and added the contextPath property to my component description (to make it consistent), which now looked like this:

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
  activate="activate" configuration-policy="ignore" enabled="true"
  immediate="true" name="test.webthing">
   <implementation class="test.webthing.WebThing"/>
   <service>
      <provide interface="org.eclipse.jetty.server.handler.ContextHandler"/>
   </service>
   <property name="contextFilePath" type="String"
     value="/jetty-web.xml"/>
   <property name="contextPath" type="String" value="/hello"/>
</scr:component>

Hopefully the requirement for a jetty.xml-file will go away in the future, but for now, I can live with it like this, but if anyone has an idea of how to make it better, let me know!

The "webthing" bundle can be downloaded here.

Saturday
Aug282010

A fond farewell to Purple Scout

So, this is it.

I switched on the alarm at the Purple Scout offices, probably for the last time. A few tears were shed and a few hugs were shared during the latter part of the evening, I'm not ashamed to admit. Purple Scout has been like a second home and family for me for the better part of four years. I pity one and all who have not been so lucky as to have experienced the camaraderie and fellowship associated with being a Purple Scout employee.

Why am I leaving Purple Scout?

All other things being equal, the reasons making the scale tip over to Procera's favor were threefold: First, for various reasons I have never been able to complete a project or product about which I have felt both engaged in and proud of, and the PSM project/product might just be it. The next opportunity for a project that I feel so strongly about had I stayed with Purple Scout would most likely be a long way away. It's a personal type of closure that I've yet to achieve. The second reason was more of a pragmatic one. When this project was removed, what was I to do? Certainly there would eventually show up some sort of task that I might perform, but I find it highly unlikely that I would get the same sort of challenges, team dynamics and sense of brotherhood that the PSM-team has. Finally, and by far the most important reason, almost the entire team of my project collectively signed the new employment contracts, with the last member having personal reasons for not doing so. We even sent all of our signed contracts in the same envelope.

And where am I going?

My new employer is Procera Networks. Can they ever provide the same incredible experience? Well, they do have some exciting challenges lined up, first and foremost the next version of our software that we need to finish, but no matter what exciting technical problems they offer, will they live up to the same standards as Purple Scout when it comes to being a good employer and, indeed, a good friend?

Only time will tell, but I suppose the only way of finding out is at the end. Whether I'm about to cry because of people and places I already miss on my way out of the door. I sure hope that will be the case.

Procera certainly does show some promise though! Besides, our team will be quite the horde of Purple People joining Procera, so their resistance will be futile. They will be assimipurpled. Purplimilated. Purplified. Or perhaps they're just that good already. We'll see.

To all of you who make up Purple Scout and its ideals, thank you for the wonderful time we've had, and a special thank you to Johan Strömhage and Kasper Aase whose dedication to their employees have been a beacon of light through economic recessions and growth alike.

Suspiciously absent above, but no less instrumental to my experience at Purple Scout is Emil Erlandsson. However, he's part of the swarm of Purple locusts currently preparing our descent upon the unsuspecting Malmö offices of Procera Networks. I'm not quite done with him yet :)

I wish Purple Scout all the best in the future and I hope to be meeting and working with all of you again!

So…

 

PSM-team is dead, long live PSM-team!

Wednesday
Nov182009

My opinions on multiple function / method exit points

I originally posted this at Stack Overflow as a response to this question. Since then some people have asked me the same questions outside, so I figured I should just post it here.

There are good things to say about having a single exit-point, just as there are bad things to say about the inevitable "arrow" programming that results.

If using multiple exit points during input validation or resource allocation, I try to put all the 'error-exits' very visibly at the top of the function.

Both the Spartan Programming article of the "SSDSLPedia" and the single function exit point article of the "Portland Pattern Repository's Wiki" have some insightful arguments around this.

If you really want a single exit-point (in any non-exception-enabled language) for example in order to release resources in one single place, I find the careful application of goto to be good; see for example this rather contrived example (compressed to save screen real-estate):

int f(int y) {
    int value = -1;
    void *data = NULL;

    if (y < 0)
        goto clean;

    if ((data = malloc(123)) == NULL)
        goto clean;

    /* More code */

    value = 1;
clean:
   free(data);
   return value;
}

Personally I, in general, dislike arrow programming more than I dislike multiple exit-points, although both are useful when applied correctly. The best, of course, is to structure your program to require neither. Breaking down your function into multiple chunks usually help :)

Although when doing so, I find I end up with multiple exit points anyway as in this example, where some larger function has been broken down into several smaller functions:

int g(int y) {
  value = 0;

  if ((value = g0(y, value)) == -1)
    return -1;

  if ((value = g1(y, value)) == -1)
    return -1;

  return g2(y, value);
}

Depending on the project or coding guidelines, most of the boiler-plate code could be replaced by macros. As a side note, breaking it down this way makes the functions g0, g1 ,g2 very easy to test individually.

Obviously, in an OO and exception-enabled language, I wouldn't use if-statements like that (or at all, if I could get away with it with little enough effort), and the code would be much more plain. And non-arrowy. And most of the non-final returns would probably be exceptions.

In short;

  • Few returns are better than many returns
  • More than one return is better than huge arrows, and guard clauses are generally ok.
  • Exceptions could/should probably replace most 'guard clauses' when possible.