Using Groovy Closures Instead of Template Method

0
95
3 min read

 

Groovy for Domain-Specific Languages

Groovy for Domain-Specific Languages

Extend and enhance your Java applications with Domain Specific Languages in Groovy

  • Build your own Domain Specific Languages on top of Groovy
  • Integrate your existing Java applications using Groovy-based Domain Specific Languages (DSLs)
  • Develop a Groovy scripting interface to Twitter
  • A step-by-step guide to building Groovy-based Domain Specific Languages that run seamlessly in the Java environment
        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.

Using Groovy Closures Instead of Template Method

LEAVE A REPLY

Please enter your comment!
Please enter your name here