Wiki

Clone wiki

jettyBuilder / Home

#JettyBuilder - A Groovy Builder for Configuring Jetty JettyBuilder allows you to embed and completely configure Jetty in your application in a declarative and concise fashion. It accomplishes this by employing a common idiom in Groovy, builders. Builders handle the busywork of creating complex objects for you, such as instantiating children, calling Jetty methods, and attaching these children to their parents. As a consequence, your code is much more readable and maintainable, while still allowing you access to the full range of Jetty components.

Here is an example of a JettyBuilder script:

#!groovy
server( port: 8095, stopAtShutdown: true, stopTimeout: 5000 ) 

In this script, we're telling the builder to create a Server using the Server(port) constructor and set its bean properties stopAtShutdown and stopTimeout to the supplied values.

JettyBuilder is aware of which settings are constructor only vs bean-like as well as the sequence of creating objects, i.e child first then parent (default) vs. parent first then child (e.g. in the case of ServerConnector[child] and Server[parent]).

Embedded

We can embed this script in an application like this:

#!groovy
class SimplestServer {
  static void main( String[] args ) throws Exception {
    server = new JettyBuilder().build {
      server( port: 8095, stopAtShutdown: true, stopTimeout: 5000 )
    }
    server.start()
  }
}

This runs an HTTP server on port 8080. Since this server has no handlers, it returns a 404 error for every request.

Script File

We can also place the builder script in a separate file with a .getty extension. JettyBuilder automatically injects a builder instance jetty. Lets call the script server.getty:

jetty.server( port: 8095, stopAtShutdown: true, stopTimeout: 5000 )

Our app changes a bit to reference the external script like this:

#!groovy
class SimplestServer {
   static void main( String[] args ) throws Exception {
    Server server = JettyBuilder.fromScript( "server.getty" )
    server.start()
  }
}

###Variables & Binding Under the hood, JettyBuilder loads the script via GroovyShell. This means we can use custom variables in our script and bind them to runtime values like this:

#!groovy
jetty.server( port: httpPort ?: 8095, stopAtShutdown: true, stopTimeout: stopTimeout: ?: 5000 ) 

Script variables can be set by providing an optional map to fromScript:

#!groovy
Server server = JettyBuilder.fromScript("server.getty", [httpPort: 8080] )

The server now runs on port 8080. Note that we didn't bind stopTimeout but since we used the Groovy elvis operator ?: in the script, the server's stopTimeout will be set to a default 5000.

###Object Ids Builder objects support a special property id. This lets us reference the object instance elsewhere in the script

#!groovy
jetty.server( id: "theServer", port: port, stopAtShutdown: true, stopTimeout: 5000 )

println theServer

Within the script, the variable theServer holds a reference to the server instance. One place this is useful is with HttpConfiguration copy constructors.

###Adding A Connector & Handlers Lets add a connector to our server and a couple of handlers:

#!groovy
jetty.server( id: "theServer", stopAtShutdown: true, stopTimeout: 5000 ) {
  connector( port: httpPort ?: 8095, host: host ?: "localhost",
      idleTimeout: 30000 )
  handlerList {
    resourceHandler( resourceBase: "/", directoriesListed: true )
    defaultHandler( showContexts: true )
  }
}

This creates an HTTP server and adds a ServerConnector object with defaults (i.e. no explicit connection factories). We also added two handlers, a ResourceHandler and a DefaultHandler for 404 handling. Also by convention, a Server can have only one direct Handler child so we wrapped the two handlers within a HandlerList.

###Implicit use of HandlerList Since we're asking the underlying builder to deal with the jetty API details, as a design decision we allow multiple top level Handler objects as direct children of a Server. In this case, we implicitly wrap multiple top-level handlers in a HandlerList. Which means this is equivalent to the above and just a bit more concise:

#!groovy
jetty.server( id: "theServer", stopAtShutdown: true, stopTimeout: 5000 ) {
  connector( port: httpPort ?: 8095, host: host ?: "localhost",
      idleTimeout: 30000 )
  resourceHandler( resourceBase: "/", directoriesListed: true )
  defaultHandler( showContexts: true )
}

###ServletHandler Here's an example of a ServletHandler with two servlets each mapped to a path:

#!groovy
jetty.server( id: "theServer", stopAtShutdown: true, stopTimeout: 5000 ) {
  connector( port: httpPort ?: 8095, host: host ?: "localhost",
      idleTimeout: 30000 )

  servletHandler servlets: [
      "/hello": "com.maestro.groovy.builders.jettyBuilder.HelloServlet",
      "/hello2": "com.maestro.groovy.builders.jettyBuilder.HelloServlet",
  ]
  defaultHandler()
}

###ServletContextHandler The following example instantiates a DefaultServlet to server static content from /tmp/ and a DumpServlet that creates a session and dumps basic details about the request:

#!groovy
jetty.server( id: "theServer", port: port, stopAtShutdown: true,
    stopTimeout: 5000 ) {

  servletContextHandler useSessions: true, contextPath: "/", servlets: [
      "/tmp/*": servletHolder( DefaultServlet,
          initParameters: [ resourceBase: "/tmp", pathInfoOnly: "true" ] ),
      "/*": servletHolder( DumpServlet ) ]
}

###WebApp The following example configures the Jetty test webapp. Web applications can use resources the container provides, and in this case a LoginService is needed and also configured:

#!groovy
jetty.server( id: "theServer", port: port, stopAtShutdown: true,
    stopTimeout: 5000 ) {
  webAppContext contextPath: "/", war: "src/test/resources/webapp/test-jetty-webapp-9.0.0-SNAPSHOT.war"

  hashLoginService name: "Test Realm", config: "src/test/resources/realm.properties"
}

Updated