The universality and practicality of Ant as a Java project Builder is beyond the scope. Even Maven, a new tool in the building area, owes much of its power to the lessons learned from Ant. However, these two workers share a common shortcoming: extensibility. Even though the portability of XML plays a major role in promoting Ant and Maven toward development, XML, as a role in building configuration formats, still limits the expressiveness of the build process more or less.
For example, although there are conditional logic in both ANT and Maven, XML representation is a bit cumbersome. Also, although custom tasks can be defined to extend the Ant build process, doing so usually limits the behavior of the application to a limited sandbox. So, in this article, I'm going to show you how Groovy and Ant can be combined within Maven to create a more powerful expressiveness that gives better behavioral control over the build process.
You'll soon see that groovy has brought an impressive boost to both Ant and Maven, and the beauty of groovy is that it often makes up for the missing XML! In fact, it seems that the creator of Groovy must have experienced the pain of implementing the Ant and Maven build process with XML because they introduced Antbuilder, a powerful new tool that supports the use of ant in Groovy scripts.
In this episode of Groovy, I'll show you how easy it is to move to Groovy as your build configuration format without XML. Closures (closure) are an important feature of Groovy and the core of the language's uniqueness, so I'm going to make a quick review of closures before I go to the next section.
Quick review of closures
Like groovy's own very famous ancestors, groovy also supports the concept of anonymous functions or closures (closure). If you've ever written code in Python or Jython, you might be familiar with closures, in both languages, with the use of lambda keywords to introduce closures. In Ruby, if you don't use blocks or closures, you have to actually write scripts. Even the Java language provides a limited form of support for anonymous functions through its anonymous inner class.
In Groovy, closures are the first level of anonymous functions that can encapsulate behavior. When Ruby's creator Yukihiro Matsumoto noticed that these powerful first class objects could be "passed to another function, and then the function could invoke the incoming [closure]", it also began to meddle with the closure application (see Resources for a full interview). Of course, handling Groovy in person is the best way to understand how much the closure is a great asset to this wonderful and exciting language.
Closure instances
In Listing 1, I've used some of the code from the 1th article in this series, but this time the focus is on closures. If you've read that article (see Resources), you can recall the Java-based packet filtering object I used to demonstrate unit testing in Groovy. This time, I started with the same example, but it was greatly enhanced with the closure. The following is a Java-based Filter interface.
Listing 1. Remember this simple Java Filter interface?
public interface Filter {
void setFilter(String fltr);
boolean applyFilter(String value);
}
Last time, after defining the Filter type, I then defined two implementations named Regexpackagefilter and Simplepackagefilter, which used both regular expressions and simple String operations.
For code that doesn't work with closures, it's good to date. In Listing 2, you'll start to see a little bit of grammatical change, and the code is different (better!). )。 I'll start by defining the generic Filter type (shown below), but this time it's defined in Groovy. Note the Strategy property associated with the Filter class. This property is an instance of the closure and can be invoked when the ApplyFilter method is executed.
Listing 2. More Groovy filters--using closures
class Filter{
strategy
boolean applyFilter(str){
return strategy.call(str)
}
}