Open-source Libraries From Our Java Web Stack

A while ago, I wrote about how to set up Guice, Jetty, Jersey, and Jackson and then how to calculate metrics about Jersey resource methods. We’ve subsequently open sourced some libraries to make it easy to use these (and other) techniques.

I’ll be describing each of our new libraries in turn, or you can skip to the end and look at a sample app to see them in action.

Jersey CORS Filter

CORS allows better cross-domain sharing of Web resources. jersey-cors-filter eases the task of adding CORS headers to Jersey resource methods. In the simple case, you can annotate a resource method with @Cors and that’s all.

Having an @Cors annotation on the method or class will result in Access-Control-Allow-Origin and other CORS headers being set on the response:

@Path("foo")
public class FooResource {
    @GET
    @Cors
    public String get() {
      return "some data";
    }
}

If you watch the log output in the sample app, you’ll see that the request that should get Access-Control-Allow-Origin is displaying the value it receives for that header.

Jersey Metrics Filter

jersey-metrics-filter is a pre-packaged and improved version of the metrics-calculating technique described in an earlier blog post. In the default config, all Jersey resource methods will have timing and status code count metrics measured for them, but that can also be customized with the @ResourceMetrics annotation.

This method would have timing measured, but status codes will not be tallied:

@GET
@ResourceMetrics(statusCodeCounter = false, timer = true)
public String get() {
    return "stuff";
}

The sample app uses Metrics’ JmxReporter to make all metrics available via JMX, so be sure to open up jconsole to take a look.

Jersey Guice Dispatch Wrapper

jersey-guice-dispatch-wrapper is used by jersey-metrics-filter to directly wrap the invocation of Jersey resource methods so that timing information can be captured accurately. Most filtering needs can be accomplished with Jersey’s ContainerRequestFilter and ContainerResponseFilter, but if you need javax.servlet.Filter-style direct wrapping of request handling, this library will simplify the Jersey boilerplate.

Jetty HTTP Server Wrapper

jetty-http-server-wrapper provides a simple way to set up an embedded Jetty HTTP server with Guice Servlet. While you can certainly set up Jetty manually, this library lets you focus more on configuration rather than the mechanics of wiring up a ServletContextHolder, etc. It also provides sane defaults for TLS ciphers and protocols.

Here’s a simple TLS HTTP server:

KeyStore keyStore = getServerKeystoreFromSomewhere();

HttpServerConnectorConfig httpsConfig = HttpServerConnectorConfig.forHttps("localhost", 8443)
    .withTlsKeystore(keyStore)
    .withTlsKeystorePassphrase("password");

httpServerFactory
    .getHttpServerWrapper(new HttpServerWrapperConfig().withHttpServerConnectorConfig(httpsConfig))
    .start();

URL Builder

url-builder provides a builder-style API for assembling correctly-encoded URLs. See this blog post for more details on why this isn’t easily done using the built-in Java libraries. A simple example:

UrlBuilder.forHost("http", "localhost", 8080)
    .pathSegment("foo")
    .queryParam("search", "some stuff")
    .toUrlString();

Jersey/New Relic Integration

jersey-new-relic lets Jersey resource requests have useful New Relic transaction names that include the value of the appropriate @Path annotations. Without this, all Jersey requests show up as being handled by ServletContainer (or GuiceContainer if you’re using Guice). It also informs New Relic of exceptions thrown during request processing.

Demo app

I’ve put together a runnable sample app that shows all of these libraries in use. Grab the code, execute gradle run, and open up jconsole to look at the generated metrics. If you have New Relic, follow the instructions in the README to have data recorded in New Relic as well.

It happens to be written in Groovy, but is easily translatable to Java. We use this style of service (embedded Jetty with simple main()-method startup) for all of our Java web services that do not have to be deployed as a .war for compatibility with existing systems.

We’ve still got a few more things to release, but this is enough to get a useful service up and running. Let us know in the comments if you have suggestions for how any of these can be improved.

Posted by Marshall Pierce

Marshall specializes in highly tuned and immensely scalable web and mobile applications. Experienced in front-end web and iOS development, he constantly pushes the boundaries of the latest browsers and mobile platforms. He splits his time with back-end development, where he is considered a domain expert in Java concurrency, distributed systems, systems design, and network security. Prior to co-founding Palomino Labs, Marshall was director of software development at Ness Computing where he led their initial launch. Before Ness, Marshall was a senior software developer at Genius.com, where he built the best-in-class integration with Salesforce.com.

About Palomino Labs

Palomino Labs unlocks the potential of software to change people and industries. Our team of experienced software developers, designers, and product strategists can help turn any idea into reality.

See the Palomino Labs website for more information, or send us an email and let's start talking about how we can work together.