Your message has been sent.
This article has been saved to your account.
Go to my account
This article has been emailed to your Kindle.
Send this article
Complete the form below to send this article, Using Groovy Closures Instead of Template Method, to a friend (or to yourself). We will never share your details (or your friend's) with anyone. For more information, read our Privacy Policy.
A good software developer always keeps the DRY principle in mind. Whenever code is duplicated, maintainability problems are introduced and the code base becomes difficult to understand. Java developers often rely on the template method pattern to reuse code. Groovy's closure programming concept is an alternative way to solve similar problems. Closures provide a concise way to pass around code without the ceremony involved with design patterns. This article by Nirav Assar will demonstrate how closures are used to embrace the DRY principle.
| Read more about this book |
(For more resources on Groovy, see here.)
Template Method Pattern Overview
The template method pattern often applies during the thought "Well I have a piece of code that I want to use again, but I can't use it 100%. I want to change a few lines to make it useful." In general, using this pattern involves creating an abstract class and varying its implementation through abstract hook methods. Subclasses implement these abstract hook methods to solve their specific problem.
This approach is very effective and is used extensively in frameworks. However, closures provide an elegant solution.
Sample HttpBuilder Request
It is best to illustrate the closure approach with an example. Recently I was developing a consumer of REST webservices with HttpBuilder. With HttpBuilder, the client simply creates the class and issues an HTTP call. The framework waits for a response and provides hooks for processing.
Many of the requests being made were very similar to one another, only the URI was different. In addition, each request needed to process the returned XML differently, as the XML received would vary. I wanted to use the same request code, but vary the XML processing. To summarize the problem:
- HttpBuilder code should be reused
- Different URIs should be sent out with the same HttpBuilder code
- Different XML should be processed with the same HttpBuilder code
Here is my first draft of HttpBuilder code. Note the call to convertXmlToCompanyDomainObject(xml).
static String URI_PREFIX = '/someApp/restApi/'
private List issueHttpBuilderRequest(RequestObject requestObj, String uriPath) {
def http = new HTTPBuilder("http://localhost:8080/")
def parsedObjectsFromXml = []
http.request(Method.POST, ContentType.XML) { req ->
// set uri path on the delegate
uri.path = URI_PREFIX + uriPath
uri.query = [
company: requestObj.company,
date: requestObj.date
type: requestObj.type
]
headers.'User-Agent' = 'Mozilla/5.0'
// when response is a success, parse the gpath xml
response.success = { resp, xml ->
assert resp.statusLine.statusCode == 200
// store the list
parsedObjectsFromXml = convertXmlToCompanyDomainObject(xml)
}
// called only for a 404 (not found) status code:
response.'404' = { resp ->
log.info 'HTTP status code: 404 Not found'
}
}
parsedObjectsFromXml
}
private List convertXmlToCompanyDomainObject(GPathResult xml) {
def list = []
// .. implementation to parse the xml and turn into objects
}
As you can see, URI is passed as a parameter to issueHttpBuilderRequest. This solves the problem of sending different URIs, but what about parsing the different XML formats that are returned?
Using Template Method Pattern
The following diagram illustrates applying the template method pattern to this problem. In summary, we need to move the issueHttpBuilderRequest code to an abstract class, and provide an abstract method convertXmlToDomainObjects(). Subclasses would provide the appropriate XML conversion implementation.

| Read more about this book |
(For more resources on Groovy, see here.)
Using Closures
Now for the closure approach. Without creating extra classes or using a formal pattern, we can solve the same problem. We can define two closures in the same class, and pass these closures into the issueHttpBuilderRequest method. The method will execute the closure when appropriate. After all, we want to identify the area of variation and insert some different code at that variation point.
Notice the added argument Closure convertXmlToDomainObjects to the issueHttpBuilderRequest method, along with two new closure definitions.
static String URI_PREFIX = '/someApp/restApi/'
private List issueHttpBuilderRequest(RequestObject requestObj, String uriPath, Closure
convertXmlToDomainObjects) {
def http = new HTTPBuilder("http://localhost:8080/")
def parsedObjectsFromXml = []
http.request(Method.POST, ContentType.XML) { req ->
// set uri path on the delegate
uri.path = URI_PREFIX + uriPath
uri.query = [
company: requestObj.company,
date: requestObj.date
type: requestObj.type
]
headers.'User-Agent' = 'Mozilla/5.0'
// when response is a success, parse the gpath xml
response.success = { resp, xml ->
assert resp.statusLine.statusCode == 200
log.info "My response handler got response: ${resp.statusLine}"
// store the list
parsedObjectsFromXml = convertXmlToDomainObjects(xml)
}
// called only for a 404 (not found) status code:
response.'404' = { resp ->
log.info 'HTTP status code: 404 Not found'
}
}
parsedObjectsFromXml
}
def convertXmlToCompanyDomainObject = { GPathResult xml ->
def list = []
// .. implementation to parse the xml and turn into objec
}
def convertXmlToCorporationObject = { GPathResult xml ->
def list = []
// .. implementation to parse the xml and turn into objec
}
Now we can call the issueHttpBuilderRequest method as follows:
def companyObjects = issueHttpBuilderRequest (request, 'companyInformation',
convertXmlToCompanyDomainObject)
def corporationObjects = issueHttpBuilderRequest (request, 'corporationInformation',
convertXmlToCorporationObject)
Summary
The template method pattern is an effective and common pattern solution. However, try using the closure approach and compare the different implementations. It's always good to have another tool in the arsenal.
On the other hand, you could achieve the same by copying and pasting code, or inserting only if statements to handle variances. Punt those options and go for the elegant approach. It's better for maintenance, easier on the eye for other developers, and makes our job easier in the long run.
Further resources on this subject:
- Metaprogramming and the Groovy MOP [article]
- Modeling Relationships with GORM [article]
- The Grails Object Relational Mapping (GORM) [article]
About the Author :
Nirav Assar is an independent consultant in the Dallas/Fort Worth area. He is co-partner at Solutionsfit, a consulting firm that assists enterprise with the development needs. Nirav has worked with several technologies professionally, such as Grails/Groovy, Seam, Spring, and Hibernate. His areas of expertise include agile methodologies, object-oriented design, test driven development, and refactoring. In his leisure time, Nirav enjoys reading, blogging, watching sports, and playing soccer. You can view his blog at Assar Java Consulting.



Post new comment