Simple Servlets in Groovy

A feature I miss in groovy is a simple way to create a self-contained web server without a web container like Tomcat. Python, in particular, has a nice solution for this with its HTTPServer class. It’s not something to write a full application with, but it’s an extremely convenient tool to have available.

The best solution I’ve found is Jetty, the embedded Java web server. It has a nice simple interface and runs any Servlet right out of your script:

@Grab(group='org.mortbay.jetty', module='jetty-embedded', version='6.1.26')
import org.mortbay.jetty.Server
import org.mortbay.jetty.servlet.*

def runWithJetty(servlet, port) {
   def jetty = new Server(port)
   def context = new Context(jetty, '/', Context.SESSIONS)
   context.addServlet(new ServletHolder(servlet), '/*')
   jetty.start()
}

Groovy has groovlets and GroovyServlet, a nice little wrapper for writing Servlets. However, it requires you to structure your project in a specific way: each Servlet in a separate file, mapped to URI paths by file name.

By hooking up ServletCategory and ServletBinding to a closure, it’s possible to get the nice features of groovlets without the GroovyServlet limitations:

@Grab(group='org.mortbay.jetty', module='jetty-embedded', version='6.1.26')
import org.mortbay.jetty.Server
import org.mortbay.jetty.servlet.*
import groovy.servlet.*
import javax.servlet.http.*
import javax.servlet.ServletConfig

class SimpleGroovyServlet extends HttpServlet {
    def requestHandler
    def context
    void init(ServletConfig config) {
        super.init(config)
        context = config.servletContext
    }
    void service(HttpServletRequest request, HttpServletResponse response) {
        requestHandler.binding = new ServletBinding(request, response, context)
        use (ServletCategory) {
            requestHandler.call()
        }
    }
    static void run(int port, Closure requestHandler) {
        def servlet = new SimpleGroovyServlet(requestHandler: requestHandler)
        def jetty = new Server(port)
        def context = new Context(jetty, '/', Context.SESSIONS)
        context.addServlet(new ServletHolder(servlet), '/*')
        jetty.start()
    }
}

Combined with the above, a simple self-contained web server becomes as clean and concise as groovy should be:

SimpleGroovyServlet.run(8080) { ->
    response.contentType = 'text/plain'
    println "hello world!"
    println "my path is ${request.pathInfo}"
    println "my params are $params"
}
  1. Ken Kousen says:

    Nicely done. I’ve been trying to figure out a way to take advantage of ServletBinding and couldn’t find one. I like how you provide a closure and replace its binding with the ServletBinding. I imagine you have a lot more sophisticated uses in mind.

    Thanks for the post. :)

  2. Erik Pragt says:

    Thanks for the article, but do you also know that there’s a command line option which will turn Groovy scripts into ‘servlets’ automatically?

    For example, try this: ‘groovy -l 8080 -e “println ‘hello world’”

    Some more explanation can be found here: http://stackoverflow.com/questions/4571594/how-to-get-post-content-with-groovy-listening-on-a-port

    Erik Pragt

    • ataylor284 says:

      Good point Erik. That’s a nice quick and dirty way to create a server. It’s line-oriented though, so getting up a bare bones HTTP server is a bit more work. You have to deal with the protocol details that jetty keeps hidden behind the Servlet interface.

    • Matt Passell says:

      Erik, did you notice that the answer to that question on Stack Overflow was added by Andrew? :)

  3. Crazy4Groovy says:

    Cool, thanks for the code snippet!

    I’m just curious how groovlets might work into this; it’s been awhile…

    • ataylor284 says:

      Looks pretty nice. Its method of mapping request paths to closures is much more flexible than the above. Also, it looks like it uses netty instead of jetty, so it’s probably more scalable.

      Definitely a good alternative for writing a simple web server in groovy.

  4. Bob Herrmann says:

    // Groovy web server using only the JDK in 8 lines please
    import com.sun.net.httpserver.*;
    HttpServer server = HttpServer.create(new InetSocketAddress(2222),0)
    server.createContext(‘/’, { HttpExchange exchange ->
    exchange.sendResponseHeaders(200,0);
    exchange.responseBody.write(‘hello from groovy land.’.bytes)
    exchange.responseBody.close();
    } as HttpHandler)
    server.start();

    • ataylor284 says:

      Very cool, a whole HTTP server hidden away in the JDK. Even so, I think I prefer pulling in jetty to use the standard servlet interface.

  1. [...] A feature I miss in groovy is a simple way to create a self-contained web server without a web container like Tomcat. Python, in particular, has a nice solution for this with its HTTPServer class. It’s not something to write a full application with, but it’s an extremely convenient tool to have available.    Groovy Read the original post on DZone… [...]