Ratpacked: Extending GroovyChain DSL
Russel Hart has a nice example on how to extend the Ratpack Groovy DSL in the hands on ratpack project on Github. We can use the Groovy extension module feature to add new methods to arbitrary classes. If we use this to add new methods to the GroovyChain
class we can use those methods in the DSL of our Groovy Ratpack application.
A Groovy extension module is just a class with a definition of the new methods we want to add to a class. The first argument of the method is the class the method is added to and the remaining arguments can be used by the implementation. We also need to create a supporting file org.codehaus.groovy.runtime.ExtensionModule
with some information about our extension class. This supporting file needs to be in the classpath in the directory META-INF/services
.
Let's first write our extension module class. Here we define the method cors
that will accept an arbitrary number of String type arguments that are added to the response header. Finally the next
method is called on the implicit Context
object to continue with the other handlers.
// File: src/main/groovy/com/mrhaki/ratpack/CorsChainExtension.groovy
package com.mrhaki.ratpack
import groovy.transform.CompileStatic
import ratpack.groovy.handling.GroovyChain
@CompileStatic
class CorsChainExtension {
// Add cors method to the GroovyChain class.
// The method accepts an arbitrary number of
// String arguments. These arguments must be
// pairs of valid response header name and value
// to support CORS.
static GroovyChain cors(
final GroovyChain chain,
final String... values) {
// Apply to all requests.
chain.all {
// Make pairs of the values passed as arguments
// and set response header for each pair.
values.toList().collate(2).each { pair ->
// Set response header name and value.
response.headers.add(
pair.first(),
pair.last())
}
// Continue with next handler.
next()
}
}
}
Next we create the supporting file to describe the extension module:
# File: src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
moduleName = corsChainExtension
moduleVersion = 1.0
extensionClasses = com.mrhaki.ratpack.CorsChainExtension
Now we can use the cars
method in our DSL:
// File: src/ratpack/ratpack.groovy
import static ratpack.groovy.Groovy.ratpack
ratpack {
handlers {
// Use new method cors.
cors 'Access-Control-Allow-Origin', '*',
'Access-Control-Allow-Methods', 'GET'
get {
render 'Welcome to Ratpack!'
}
}
}
When we make a request for http://localhost:5050/
we can see in the response headers the names and values we have defined with the cors
method:
$ http localhost:5050
Access-Control-Allow-Methods: GET
Access-Control-Allow-Origin: *
connection: keep-alive
content-encoding: gzip
content-type: text/plain;charset=UTF-8
transfer-encoding: chunked
Welcome to Ratpack!
$
In IntelliJ IDEA we even get code completion on our new method:
Written with Ratpack 1.1.1.
Original article