Often, programmers turn to languages like Groovy for building quick utilities, rapidly writing test code, and even for creating components that make up larger Java applications because of Groovy's innate ability to remove much of the noise and complexity that accompanies typical Java-based systems. Groovy's concise, yet flexible syntax frees developers from normal Java constructs that are required for code compilation but don't necessarily help express what the program is really trying to accomplish. What's more, Groovy's relaxed typing removes perceived code complexity through the reduction of interfaces and super classes, which are required in normal Java applications to support common behavior among distinct concrete types.
As an example of how Groovy can reduce the associated noise of a plain old Java application, I'll use sample code from Bruce Tate and Justin Ghetland's Spring: A Developer's Notebook (Resources), which introduces Inversion of Control with Spring. As I review each Java example, I'll make a comparison to corresponding Groovy source that is functionally equivalent, and I think you'll see quite quickly how much clearer Groovy makes application code by reducing various aspects of Java programming, which are noisy and don't necessarily convey an application's behavior.
In the first chapter of Bruce and Justin's book, they create a simple bike store application, which has
four different classes. First, I'll show you a simple JavaBean
class named Bike, which represents a bicycle in stock. Then, I'll examine a bike store type, dubbed RentABike, which contains a collection of Bikes.
There is also a class for displaying a list of bikes, aptly named CommandLineView, which depends on the RentABike type. Finally, there is a class responsible for assembling the parts to create
a working application, which utilizes Spring to deliver the CommandLineView class fully
configured with the RentABike type -- free of hardwiring.
The class that represents a bike, found in Listing 1, is implemented as a simple JavaBean in normal Java code and is representative of hundreds of classes that Java developers have probably written. Typically, there is nothing special about JavaBeans -- properties are declared as private
and are accessed through public getters and setters.
Listing 1. A Bike JavaBean in Java code
import java.math.BigDecimal;
public class Bike {
private String manufacturer;
private String model;
private int frame;
private String serialNo;
private double weight;
private String status;
private BigDecimal cost;
public Bike(String manufacturer, String model, int frame,
String serialNo, double weight, String status) {
this.manufacturer = manufacturer;
this.model = model;
this.frame = frame;
this.serialNo = serialNo;
this.weight = weight;
this.status = status;
}
public String toString() {
return "com.springbook.Bike : " +
"manufacturer -- " + manufacturer +
"\n: model -- " + model +
"\n: frame -- " + frame +
"\n: serialNo -- " + serialNo +
"\n: weight -- " + weight +
"\n: status -- " + status +
".\n"; }
public String getManufacturer() { return manufacturer; }
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getModel() { return model; }
public void setModel(String model) { this.model = model; }
public int getFrame() { return frame; }
public void setFrame(int frame) { this.frame = frame; }
public String getSerialNo() { return serialNo; }
public void setSerialNo(String serialNo) { this.serialNo = serialNo; }
public double getWeight() { return weight; }
public void setWeight(double weight) { this.weight = weight; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public BigDecimal getCost() { return cost; }
public void setCost(BigDecimal cost) {
this.cost = cost.setScale(3,BigDecimal.ROUND_HALF_UP);
}
}
|
Whew! Listing 1 is a small example with only one constructor and six properties, but the code comes close to filling the entire page of a browser! Listing 2 shows the same JavaBean defined in Groovy:
Listing 2. A Bike GroovyBean
class Bike {
String manufacturer
String model
Integer frame
String serialNo
Double weight
String status
BigDecimal cost
public void setCost(BigDecimal newCost) {
cost = newCost.setScale(3, BigDecimal.ROUND_HALF_UP)
}
public String toString() {
return """Bike:
manufacturer -- ${manufacturer}
model -- ${model}
frame -- ${frame}
serialNo -- ${serialNo}
"""
}
}
|
Which one do you think is less noisy?
The Groovy version is much, much smaller because Groovy's default property semantics automatically
define a private field
with public accessors and mutators. For example,
the property model from above
now has the equivalent of a getModel() and setModel() method
automatically defined. As you can see, this technique has the benefit of eliminating two hand-coded
methods per property defined in a type! This also illustrates a recurring theme in Groovy: Make common coding conventions simple.
What's more, with Groovy, the
default functionality of a class is expressed more concisely compared to what must be coded
explicitly in normal Java code (like in Listing 1).
When there is a need to do something special with a constructor or a
getter or setter, Groovy really shines because the interesting
behavior becomes immediately obvious, just by glancing at the code! For example,
it's easy to see in Listing 2 that the setCost() method
is going to scale the cost property to three decimal places.
Compare this unobtrusive Groovy code to the Java source in Listing 1. The first time you read the listing, did you notice that the setCost() method had special
functionality sprinkled in it? Unless you looked carefully, it's pretty easy to overlook!
The test case for the Bike class in Listing 3 demonstrates the
use of the automatically generated accessor. Also, in the spirit of further simplification
for common programming tasks, the test case also uses the more convenient Groovy
dot property name notation for accessing properties. Accordingly, I am able to
reference the model property either
through the getModel() method or more concisely as b.model.
Listing 3. A Bike Test Case in Groovy
class BikeTest extends GroovyTestCase {
void testBike() {
// Groovy way to initialize a new object
def b = new Bike(manufacturer:"Shimano", model:"Roadmaster")
// explicitly call the default accessors
assert b.getManufacturer() == "Shimano"
assert b.getModel() == "Roadmaster"
// Groovier way to invoke accessors
assert b.model == "Roadmaster"
assert b.manufacturer == "Shimano"
}
}
|
Also notice that in the Groovy examples above, I didn't have to define a constructor that accepts all six properties like the Java constructor defined in Listing 1. Additionally, I didn't have to create yet another constructor that only takes two arguments to support my test case -- Groovy's semantics for setting object properties during object creation removes the need for those noisy, annoying constructors with various argument combinations that do little but initialize variables.
In the previous section, the Bike GroovyBean took advantage of Groovy's property and constructor semantics to remove noise from the source code. In this section, the Groovy version of the bike store will also benefit from additional noise-reduction features such as duck-typing for polymorphism, collection class enhancements, and operator overloading.
In the Java bike application, an interface, dubbed RentABike, is used to define the public methods supported by the bike store. As demonstrated in Listing 4, RentABike defines some simple methods
for returning a single Bike or a list of all the Bikes
in the store:
Listing 4. A RentABike interface defined in Java
import java.util.List;
public interface RentABike {
List getBikes();
Bike getBike(String serialNo);
void setStoreName(String name);
String getStoreName();
}
|
This interface enables polymorphic behavior and thus provides flexibility in two important scenarios. First, if there is a decision to change the implementation, say, from an ArrayList to a database, the rest of the application is insulated from that change. Also, using interfaces
provides flexibility during unit testing. For example, if there is a decision to use a database
for the application, you can easily create a mock implementation of the type which doesn't depend on a live database.
Listing 5 shows a plain old Java implementation of the RentABike interface
using an ArrayList to store instances of
the Bike class:
Listing 5. A Java implementation of the RentABike interface
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListRentABike implements RentABike {
private String storeName;
final List bikes = new ArrayList();
public void setStoreName(String name) {
this.storeName = name;
}
public String getStoreName() {
return storeName;
}
public ArrayListRentABike(String storeName) {
this.storeName = storeName;
bikes.add(new Bike("Shimano", "Roadmaster", 20, "11111", 15, "Fair"));
bikes.add(new Bike("Cannondale", "F2000 XTR", 18, "22222",12, "Excellent"));
bikes.add(new Bike("Trek","6000", 19, "33333", 12.4,"Fair"));
}
public String toString() { return "com.springbook.RentABike: " + storeName; }
public List getBikes() { return bikes; }
public Bike getBike(String serialNo) {
Iterator iter = bikes.iterator();
while(iter.hasNext()) {
Bike bike = (Bike)iter.next();
if(serialNo.equals(bike.getSerialNo())) return bike;
}
return null;
}
}
|
Now compare the Java code in Listings 4 and 5 to the Groovy code in Listing 6. The
Groovy version cleverly obviates the need for the RentABike
interface!
Listing 6. Groovy's ArrayListRentABike implementation
public class ArrayListRentABike {
String storeName
List bikes = []
public ArrayListRentABike(){
// add new instances of Bike using Groovy's initializer syntax
bikes << new Bike(manufacturer:"Shimano", model:"Roadmaster",
frame: 20, serialNo:"11111", weight:15, status:"Fair")
bikes << new Bike(manufacturer:"Cannondale", model:"F2000",
frame: 18, serialNo:"22222", weight:12, status:"Excellent")
bikes << new Bike(manufacturer:"Trek", model:"6000",
frame: 19, serialNo:"33333", weight:12.4, status:"Fair")
}
// Groovy returns the last value if no return statement is specified
public String toString() { "Store Name:=" + storeName }
// Find a bike by the serial number
def getBike(serialNo) { bikes.find{it.serialNo == serialNo} }
}
|
Groovy, like other dynamic languages such as Smalltalk or Ruby, supports
polymorphism with "duck typing" -- at runtime, if an object acts like a duck, it is
treated like a duck, thus supporting polymorphism without interfaces. With the Groovy ArrayListRentABike implementation, not only are there fewer
lines of code, complexity has been reduced by having one less module to create and maintain.
That's some serious noise reduction!
In addition to duck typing, the default property semantics in Listing
6 concisely define two ordinary properties, storeName and
bikes, as having getters and setters. This is the same benefit
as was illustrated in the JavaBean-GroovyBean comparison from Listings 1 and 2.
Furthermore, Listing 6 also illustrates another Groovy feature that
quells code noise -- operator overloading. Notice how you can use the << operator instead of the add()
method. Code readability is improved by removing one level of nested parentheses. This
is another one of the
many seemingly small features in Groovy that facilitates code readability through the
reduction of noise.
The duck-typing and property semantics in Groovy help remove noise by reducing the number of source
lines of code; however, you can also remove noise by adding transparency. In Listing 6, notice the way the
new Bike objects are created in ArrayListRentABike's constructor. The Groovy name and value initializer
syntax is a little more verbose than the Java version, but
the additional code adds clarity -- it's immediately obvious which
properties are initialized to which values. Compare that to the Java version in Listing 5. Without
looking back at the Bike JavaBean source, can you remember which parameter is the frame and which is the weight for new Bike("Shimano", "Roadmaster", 20, "11111",
15, "Fair")? I just wrote it and I can't!
A smaller, groovier bike store view
So far, I've compared the Bike and bike store types in both Java and Groovy.
Now it's time to
take a closer look at the bike store view. In Listing 7, the view class has one property, rentaBike, which
references the RentABike interface and demonstrates the Java version of polymorphism in action. Because Java requires a declared type for all class properties,
instead of coding to a specific implementation, I code
to an interface, which insulates this class from
changes to a RentABike implementation. This is good, solid Java programming practice.
Listing 7. The Java version of the bike store view
public class CommandLineView {
private RentABike rentaBike;
public CommandLineView() {}
public void setRentaBike(RentABike rentaBike) {
this.rentaBike = rentaBike;
}
public RentABike getRentaBike() { return this.rentaBike; }
public void printAllBikes() {
System.out.println(rentaBike.toString());
Iterator iter = rentaBike.getBikes().iterator();
while(iter.hasNext()) {
Bike bike = (Bike)iter.next();
System.out.println(bike.toString());
}
}
}
|
Comparing the Java view in Listing 7 to the Groovy version in Listing 8, notice that I declare the rentaBike property with the def keyword.
This is the duck-typing in action and just like the Java version, I'm practicing good software design
because I haven't coupled my view to
a specific implementation. But I also was able to achieve this decoupling without defining an
interface.
Listing 8. Groovy's CommandLineView
public class CommandLineView {
def rentaBike // no interface or concrete type required, duck typing in action
def printAllBikes() {
println rentaBike
rentaBike.bikes.each{ println it} // no iterators or casting
}
}
|
As with the Bike and bike store types, the Groovy's CommandLineView doesn't have
the noise of an explicitly coded getter or setter for the RentABike property. Also, in the printAllBikes() method,
I again take advantage of Groovy's powerful enhancements for collections by using each to print each bike found in the collection.
In the previous sections, we have seen how Groovy compares to Java in defining a bike, a bike store, and a bike store view. It is now time review how to assemble the whole application and use the command line view to display the list of bikes in inventory using Spring.
In Java programming, once you have defined an interface, you can delegate responsibility for the creation of an actual implementation class to an object factory using the factory pattern.
Using Spring as a factory is a great noise reducer and also happens to work well in both Groovy and
Java, and in the final code examples, Spring
is going to be responsible for creating an instance of the CommandLineView type in both Java and Groovy.
In Listing 9, Spring is configured to create and inject
the ArrayList implementation of the bike store into CommandLineView before returning an instance of CommandLineView. This means that I don't have to reference the ArrayList implementation in either the Java or Groovy
version of the command line view in Listings 7 and 8.
In the Java version, the class being injected
will almost always reference an interface, not the implementation. In Groovy, using the def
keyword allows me to take advantage of duck-typing. In either case, Spring is now configured to deliver
an instance of the bike store view fully configured with an instance of a bike store type!
Listing 9. The Spring configuration file
<beans>
<bean id="rentaBike" class="ArrayListRentABike">
<property name="storeName"><value>"Bruce's Bikes (spring bean)"</value></property>
</bean>
<bean id="commandLineView" class="CommandLineView">
<property name="rentaBike"><ref bean="rentaBike"/></property>
</bean>
</beans>
|
In Listings 10 and 11, the bike
store assembler types create an instance of Spring's ClassPathXmlApplicationContext with the configuration file in Listing 9 and then request an instance of a bike store view:
Listing 10. Java version of calling Spring to create the bike store view
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class RentABikeAssembler {
public static final void main(String[] args) {
// Create a Spring application context object
ClassPathXmlApplicationContext ctx =
new ClassPathXmlApplicationContext("RentABike-context.xml");
// retrieve an object from Spring and cast to a specific type
CommandLineView clv = (CommandLineView)ctx.getBean("commandLineView");
clv.printAllBikes();
}
}
|
Note in the Java version in Listing 10, the call to Spring for requesting an instance of the command line view requires a cast to an object type that supports the printAllBikes() method. In this case, the object coming out of Spring
is being cast to CommandLineView.
With Groovy and its support for duck-typing, there is
no casting involved. I just have to make sure that the class returned by Spring can respond
to the appropriate method call, which is printAllBikes().
Listing 11. Groovy's version of Spring assembly
import org.springframework.context.support.ClassPathXmlApplicationContext
class RentABikeAssembler {
public static final void main(String[] args) {
// Create a Spring application context object
def ctx = new ClassPathXmlApplicationContext("RentABike-context.xml")
//Ask Spring for an instance of CommandLineView, with a
//Bike store implementation set by Spring
def clv = ctx.getBean("commandLineView")
//duck typing again
clv.printAllBikes()
}
}
|
As you can see in Listing 11, not only does duck-typing in Groovy help reduce noise by removing the need to declare interfaces to support auto-configuration of an object by Spring, it also simplifies using the fully configured bean once it is returned from the Spring container.
Hopefully, I've demonstrated the power of Groovy and how it can profoundly change the nature of source code. In contrast to the Java examples found above, Groovy code is smaller and easier to understand. Everyone from experienced Java architects to non-Java programmers can easily grasp the intention of the code. With Groovy and its support for dynamic typing, there are fewer files to manage, too. All in all, using Groovy removes a significant amount of noise that accompanies our typical Java programs. And that's a pleasant sound indeed!
Learn
- "Practically Groovy: Stir some Groovy into your Java apps" (Andrew Glover, developerWorks, May 2005): It's easy to mix some Groovy into your Java applications.
- "Practically Groovy: Smooth operators" (Andrew Glover, developerWorks, October 2005): An in-depth look at operator overloading with Groovy.
- "Introduction to Spring using Swing" (Chad Woolley, developerWorks, November 2005): Work through a tutorial about Inversion of Control using Spring.
- "Introduction to Spring 2 and JPA" (Sing Li, developerWorks, August 2006): Build a Web application from scratch, step-by-step, assisted by the Spring 2 Framework.
- Spring: A Developer's Notebook (Bruce A. Tate and Justin Gehtland, O'Reilly, 2005): A quick introduction to various ways Spring can be used to enhance your application.
- "Patterns in action" (Jochen Krebs, developerWorks, May 2006): For software developers unfamiliar with patterns and their various relationships, this article provides an overview of pattern usage in the context of an actual software development project.
-
The Groovy Home Page: Lots
of resources for people who are new to Groovy: FAQ, IRC
channel, mailing list, and wiki, as well as details about migrating to the
updated syntax for property access.
-
The Practically Groovy series: Tips and tricks for Groovy programmers.
- developerWorks Java technology zone: Find hundreds of articles about every aspect of Java programming.
Discuss
-
developerWorks blogs: Get involved in the developerWorks community!
Scott Hickey is a Java consultant with Bass and Associates. He has been developing software for over 20 years and working with Java since 1998. He is also the lead developer for the Groovy Eclipse Plugin.




