Web-apps using Groovlets
When you feel that a framework is way too much, but you still want to leverage Groovy for your web application, you may use some Groovlets.
Groovlets are like Groovy scripts for a web application. They are run on request having the whole web context (request, response, etc.) bound to the evaluation context.
This means:
- live reloading (if you are able to sync files with your webapp).
- no clumsy
web.xml
configuration - no groovy compiler, the groovy.jar is the only dependency
Using groovlets
Setup
To setup a webapp for Groovlets:
-
Configure the handling servlet in your
web.xml
<!-- setup the GroovyServlet in your web.xml and bind the script file extension --> <servlet> <servlet-name>groovlets</servlet-name> <servlet-class>groovy.servlet.GroovyServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>groovlets</servlet-name> <url-pattern>*.groovy</url-pattern> </servlet-mapping>
-
Add groovy.jar dependency to your project, for example with gradle:
apply plugin: 'groovy' // java is ok too apply plugin: 'war' repositories { mavenCentral() mavenLocal() } dependencies { providedCompile 'javax.servlet:servlet-api:2.5' compile 'org.codehaus.groovy:groovy-all:2.2.0' }
Handle a GET
Output HTML on GET request is pretty easy using the built-in MarkupBuilder
// if present use name parameter from
// query string (eg. ?name=Francesco)
// else use "World"
def name = params.name ?: "World"
// output some html
html.html {
head {
title "Hello from Groovlet!"
}
body {
h1 "Hello, ${name}!"
}
}
In the example above you see also Groovy native template engine: (G)String concatenation.
Handle a POST
With built-in variables bound from the Servlet request via the GrailsServlet
, you can also perform more complicated operation like handling some JSON in POST request.
response.contentType = 'application/json'
// Access headers, with context bound variable
if (headers['Content-Type'] != "application/json") {
throw new RuntimeException("Please use 'application/json' header")
}
// Get content from POST body
def jsonContent = request.reader.text
// Parse JSON to Map
def content = null
if (jsonContent) {
content = new JsonSlurper()
.parseText(jsonContent)
}
// build JSON output
json."echo" {
"original" content
}
Dealing with the JSON payload is really easy
$ curl -X POST -H "Content-Type:application/json" -d '{"name": "Ben"}' \
http://localhost:8080/groovlets-webapp-sample/echo.groovy
{"echo":{"original":{"name":"Ben"}}}
in the example above we leverage both a JsonSlurper to parse POST request body and the built-in JsonBuilder to convert a Java Map to the JSON payload of the response.
Pros and Cons
Pros:
- A simple way to leverage the power of Groovy in a web-application
Cons:
- Things can get messy as the complexity grows (switch to Grails)
- You do not have a framework and you could end reinventing the (switch to Grails)
Download
Sample web-app with source code available for download here.
Under the hood
The magic happens in the GroovyServlet that is responsible for executing the script, passing the web context to a GroovyConsole created ad-hoc.
// snippet from
// GroovyServlet.service(HttpServletRequest request,
// HttpServletResponse response)
final ServletBinding binding = new ServletBinding(request, response, servletCtx);
setVariables(binding);
// Run the script
Closure closure = new Closure(gse) {
public Object call() {
try {
GroovyScriptEngine gse = getDelegate()
return gse.run(scriptUri, binding);
} catch (ResourceException e) {
throw new RuntimeException(e);
} catch (ScriptException e) {
throw new RuntimeException(e);
}
}
};
GroovyCategorySupport.use(ServletCategory.class, closure);
The full source for GroovyServlet, more info about Groovlets