Simple Servlets in Groovy
Posted in Code on February 29th, 2012 by ataylor284 – 12 CommentsA 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"
}