Groovy for Domain-specific Languages - Second Edition

(nextflipdebug2) #1
Chapter 5

[ 95 ]

We can then make use of this closure class in our Groovy code as normal.
Groovy will match closure invocations with a String parameter and will throw a
MethodMissingException for all others. Our closure will behave in the same way as
if it was declared in Groovy:


given: "an instance of a Java Closure"
def stringParams = new MyClosure(this)
when: "Invoking this with the parameters defined by the doCall"
stringParams "String"
then: "we expect them to work"
notThrown Exception
when: "we pass an incorrect type for the doCall parameter"
stringParams 1
then: "we expect that Groovy won't find a matching Closure"
thrown MissingMethodException

Closures declared using the regular Groovy method only have a single method
signature. However, when declaring a closure in Java, we can add as many
overloaded doCall methods as we like. It's also feasible to declare a closure in Java
that did not implement doCall at all and overloaded the call methods of closure
instead. However, according to the documentation for groovy.lang.Closure, this
will have the unwanted side effect of disallowing the use of the unnamed () calling
syntax, so it should be avoided.


Finding a named closure field


All of the previous techniques for calling a closure rely on us having prior
knowledge of a field or variable that contains a closure. This is fine for most
straightforward applications of closures, but this book is about developing DSLs,
so let's dig a little deeper.


Take the Grails application framework as an example. You can download Grails
from http://grails.org/Download. Grails uses closures as a neat way of defining
actions for its user interface controllers. No further configuration is required for the
Grails runtime to be able to dispatch requests to an action:


class UserController {
....
def login = {
.... Login closure code
}
}
Free download pdf