Monday, November 30, 2009

Groovy: Java Enum Generation from XML

Besides the obvious use of Groovy to write applications, Groovy is also very useful for performing Java development related tasks such building applications, deploying applications, and managing/monitoring applications. In this post, I look at an example of generating a Java enum from XML source using Groovy.

I have previously blogged on slurping XML with Groovy. That technique is used again here. The Groovy code that follows uses this technique to read the source XML and then writes out a 100% compilable Java enum called AlbumsEnum.java. The Groovy script is shown next.


#!/usr/bin/env groovy
// generateAlbumsEnumFromXml.groovy
//
// Demonstrates use of Groovy's XML slurping to generate
// a Java enum from source XML.
//

// Set up enum attributes' names and data types
attributes = ['albumTitle' : 'String', 'artistName' : 'String', 'year' : 'int']

// Base package name off command-line parameter if provided
packageName = args.length > 0 ? args[0] : "albums"

NEW_LINE = System.getProperty("line.separator")
SINGLE_INDENT = ' '
DOUBLE_INDENT = SINGLE_INDENT.multiply(2)
outputFile = new File("AlbumsEnum.java")
outputFile.write "package ${packageName};${NEW_LINE.multiply(2)}"
outputFile << "public enum AlbumsEnum${NEW_LINE}"
outputFile << "{${NEW_LINE}"

outputFile << generateEnumConstants()

// Build enum attributes
attributesSection = new StringBuilder();
attributesAccessors = new StringBuilder();
attributesCtorSetters = new StringBuilder();
attributes.each
{
attributesSection << generateAttributeDeclaration(it.key, it.value)
attributesAccessors << buildAccessor(it.key, it.value) << NEW_LINE
attributesCtorSetters << buildConstructorAssignments(it.key)
}
outputFile << attributesSection
outputFile << NEW_LINE

outputFile << generateParameterizedConstructor(attributes)
outputFile << NEW_LINE

outputFile << attributesAccessors

outputFile << '}'

def String generateEnumConstants()
{
// Get input from XML source
albums = new XmlSlurper().parse("albums.xml")
def enumConstants = new StringBuilder()
albums.Album.each
{
enumConstants << SINGLE_INDENT
enumConstants << it.@artist.toString().replace(' ', '_').toUpperCase() << '_'
enumConstants << it.@title.toString().replace(' ', '_').toUpperCase()
enumConstants << "(\"${it.@title}\", \"${it.@artist}\", ${it.@year.toInteger()}),"
enumConstants << NEW_LINE
}
// Subtract three off end of substring: one for new line, one for extra comma,
// and one for zero-based indexing.
returnStr = new StringBuilder(enumConstants.toString().substring(0, enumConstants.size()-3))
returnStr << ';' << NEW_LINE.multiply(2)
return returnStr
}

def String generateAttributeDeclaration(String attrName, String attrType)
{
return "${SINGLE_INDENT}private ${attrType} ${attrName};${NEW_LINE}"
}

def String buildAccessor(String attrName, String attrType)
{
returnStr = new StringBuilder()
returnStr << SINGLE_INDENT << "public ${attrType} get${capitalizeFirstLetter(attrName)}()" << NEW_LINE
returnStr << SINGLE_INDENT << '{' << NEW_LINE
returnStr << DOUBLE_INDENT << "return this.${attrName};" << NEW_LINE
returnStr << SINGLE_INDENT << '}' << NEW_LINE
return returnStr
}

def String generateParameterizedConstructor(Map<String,String> attributesMap)
{
constructorInit = new StringBuilder()
constructorInit << SINGLE_INDENT << 'AlbumsEnum('
attributesMap.each
{
constructorInit << "final ${it.value} new${capitalizeFirstLetter(it.key)}, "
}
constructorFinal = new StringBuilder(constructorInit.substring(0, constructorInit.size()-2))
constructorFinal << ')'
constructorFinal << NEW_LINE << SINGLE_INDENT << '{' << NEW_LINE
constructorFinal << attributesCtorSetters
constructorFinal << SINGLE_INDENT << "}${NEW_LINE}"
return constructorFinal
}

def String buildConstructorAssignments(String attrName)
{
return "${DOUBLE_INDENT}this.${attrName} = new${capitalizeFirstLetter(attrName)};${NEW_LINE}"
}

def String capitalizeFirstLetter(String word)
{
firstLetter = word.getAt(0)
uppercaseLetter = firstLetter.toUpperCase()
return word.replaceFirst(firstLetter, uppercaseLetter)
}


The XML source that this script is run against is shown next:


<?xml version="1.0"?>
<Albums>
<Album title="Frontiers" artist="Journey" year="1983">
<Song title="Separate Ways" peak="8" />
<Song title="Send Her My Love" peak="23" />
<Song title="Faithfully" peak="12" />
</Album>
<Album title="Hysteria" artist="Def Leppard" year="1987">
<Song title="Hysteria" peak="10" />
<Song title="Animal" peak="19" />
<Song title="Women" />
<Song title="Pour Some Sugar On Me" peak="2" />
<Song title="Love Bites" peak="1" />
<Song title="Armageddon It" peak="3" />
<Song title="Rocket" peak="15" />
</Album>
<Album title="The Joshua Tree" artist="U2" year="1987">
<Song title="With or Without You" peak="1" />
<Song title="I Still Haven't Found What I'm Looking For" peak="1" />
<Song title="Where The Streets Have No Name" peak="13" />
<Song title="In God's Country" peak="14" />
</Album>
<Album title="Songs from the Big Chair" artist="Tears for Fears" year="1985">
<Song title="Shout" peak="1" />
<Song title="Everybody Wants to Rule the World" peak="1" />
<Song title="Head Over Heels" peak="3" />
<Song title="Mothers Talk" peak="27" />
</Album>
</Albums>


When the Groovy script is run against this source XML, the Java enum that it generates is shown next.


package albums;

public enum AlbumsEnum
{
JOURNEY_FRONTIERS("Frontiers", "Journey", 1983),
DEF_LEPPARD_HYSTERIA("Hysteria", "Def Leppard", 1987),
U2_THE_JOSHUA_TREE("The Joshua Tree", "U2", 1987),
TEARS_FOR_FEARS_SONGS_FROM_THE_BIG_CHAIR("Songs from the Big Chair", "Tears for Fears", 1985);

private String albumTitle;
private String artistName;
private int year;

AlbumsEnum(final String newAlbumTitle, final String newArtistName, final int newYear)
{
this.albumTitle = newAlbumTitle;
this.artistName = newArtistName;
this.year = newYear;
}

public String getAlbumTitle()
{
return this.albumTitle;
}

public String getArtistName()
{
return this.artistName;
}

public int getYear()
{
return this.year;
}

}


There are, of course, many ways in which this simple draft script could be improved and many features could be added to it. However, it serves the purpose of illustrating how easy it is to use Groovy to generate Java code from source data such as XML.

Friday, November 27, 2009

Slurping XML with Groovy

In the early days of using Java in conjunction with XML, it often seemed more difficult than it should be to use the Java programming language with the XML markup language. Besides the non-trivial and often differently implemented DOM and SAX APIs, simply finding the correct version of Xerces (and later, Crimson) without having too many conflicting versions of that library was also a common problem. This environment led to the creation and successively received JDOM project. Later developments such as the introduction of the standard Java XML parsing API of JAXP (JDK 1.4) and the inclusion of JAXB in Java SE 6 (and other Java/XML binding libraries available separately) would make parsing and working with XML in Java much easier. Groovy continues these advances in ease of Java/XML integration. In this blog post, I look at how use of Groovy's XmlSlurper makes XML parsing refreshingly easy and almost transparent.

The following simple XML code will be used to demonstrate Groovy's XmlSlurper. The XML file for this example is called RockAndRoll.xml.

RockAndRoll.xml

<Albums>
<Album title="Frontiers" artist="Journey" year="1983">
<Song title="Separate Ways" peak="8" />
<Song title="Send Her My Love" peak="23" />
<Song title="Faithfully" peak="12" />
</Album>
<Album title="Hysteria" artist="Def Leppard" year="1987">
<Song title="Hysteria" peak="10" />
<Song title="Animal" peak="19" />
<Song title="Women" />
<Song title="Pour Some Sugar On Me" peak="2" />
<Song title="Love Bites" peak="1" />
<Song title="Armageddon It" peak="3" />
<Song title="Rocket" peak="15" />
</Album>
<Album title="The Joshua Tree" artist="U2" year="1987">
<Song title="With or Without You" peak="1" />
<Song title="I Still Haven't Found What I'm Looking For" peak="1" />
<Song title="Where The Streets Have No Name" peak="13" />
<Song title="In God's Country" peak="14" />
</Album>
<Album title="Songs from the Big Chair" artist="Tears for Fears" year="1985">
<Song title="Shout" peak="1" />
<Song title="Everybody Wants to Rule the World" peak="1" />
<Song title="Head Over Heels" peak="3" />
<Song title="Mothers Talk" peak="27" />
</Album>
</Albums>


The next code snippet shows some Groovy code using XMLSlurper to print out some details based on this source XML. The Groovy script in this case is called slurpXml.groovy.

slurpXml.groovy

#!/usr/bin/env groovy
// slurpXml.groovy
// Demonstrates use of Groovy's XML slurping.
//

albums = new XmlSlurper().parse("RockAndRoll.xml")

albums.Album.each
{
println "${it.@artist}'s album ${it.@title} was released in ${it.@year}."
it.Song.each
{
println "\tFeaturing ${it.@title} that peaked in the U.S. at ${it.@peak}"
}
}


As the Groovy code above demonstrates, only a few lines of code are required to parse the XML and to print out its results as part of longer strings. The single line new XmlSlurper().parse("RockAndRoll.xml") is all it takes to parse the source XML. Then the variable to which those results are assigned (in this case, albums) provides access to the XML content via familiar syntax.

When the Groovy code above is executed, its results look like those shown in the following screen snapshot.



The Groovy User Guide has a section devoted to coverage of Reading XML Using Groovy's XmlSlurper. This section points out additional issues related to using Groovy's XmlSlurper such as dealing with XML tag names that include hyphens (use double quotes around name with hyphen included) and namespace matching details.

Conclusion

Because Groovy really is Java, Groovy can make use of the plethora of XML handling APIs for Java. However, Groovy can and does go beyond this and provides even easier-to-use APIs for XML manipulation. Groovy's XmlSlurper is an example of how Groovy makes XML reading/parsing/slurping easier than ever.

Additional References

Besides the Groovy User Guide section on XmlSlurper, there are many other online resources that cover use of XmlSlurper. I list some of them here.

Reading XML Using Groovy's XmlSlurper

Groovy: Processing Existing XML (6 March 2009)

Practically Groovy: Building, Parsing, and Slurping XML (19 May 2009)

Nothing Makes You Want Groovy More than XML (12 March 2008)

Updating XML with XmlSlurper

Groovy XMLSlurper

Tuesday, November 24, 2009

Where Have All the Groovy Licenses Gone?

One of the nice things about working with Groovy is the ready availability of good online documentation (both supplied via the Groovy site and by third parties via articles, blogs, and presentations) and the availability of several books on Groovy. I was surprised, however, when I tried to find a valid online link to the Groovy license to include in my Rocky Mountain Oracle Users Group Training Days 2010 paper "Applied Groovy: Scripting for Java Development."

I did not see a direct link to license information on the main Groovy page, so I turned to my favorite tool in such cases: the Google search engine. The next two images show the top results from search for the two words "Groovy license" both with and without quotes. The results provides several links to licenses about products related to Groovy and to things with the word "groovy" that have nothing to do with Java or software development.





Limiting the Google search to links about "license" specifically results in more tailored responses, but the license references still seem to be mostly related to products affiliated with or based on Groovy rather than Groovy itself.



The searches did help turn up mention of the Groovy license on the Groovy FAQ page. The next image shows the FAQ entry regarding the Groovy license (explaining that it is a BSD/Apache 2 style license) and the image after that one shows that the provided link does NOT point to a valid page.





The second link ("Project License") on this Groovy FAQ page is in the top left corner of the page, but it also points to a non-existent page. The next two images show the link and the non-existent page it points to.





So far, it has turned out to be more difficult than one would have guessed it to be to get a link to a valid page containing the license applicable to Groovy. However, one of the searches did point to this page with a Groovy 1.0 license. Unfortunately, this page (a portion of which is shown in the next screen image) is neither on the official Groovy site nor it is applicable to Groovy 1.6.5.



Although I was surprised at how difficult it was to find a current working link to the license applicable to Groovy 1.6.5 online, the good news is that a text file dealing with the license is bundled with the Groovy distribution. The next screen image shows the existence of this file (LICENSE.txt) in the Groovy installation directory.



As the image above demonstrates, there are other files related to licenses in this same directory. These licenses apply to products that Groovy makes use of such as Apache Commons CLI (CLI-LICENSE.txt, an Apache 2 license), the ASM bytecode manipulation framework (ASM-LICENSE.txt), and ANother Tool for Language Recognition (ANTLR-LICENSE.txt). The LICENSE.txt file basically summarizes the licensing of Groovy as being the Apache 2 license and provides that URL: http://www.apache.org/licenses/LICENSE-2.0.

In summary, the LICENSE.txt file included with the Groovy 1.6.5 distribution states, 'Licensed under the Apache License, Version 2.0 (the "License").'

Monday, November 23, 2009

The Positive Impact of Java Users Groups

The last Java.net poll asked "Do you belong to a Java users group?" and of the nearly 300 votes (at time of this writing), well over half of the respondents stated that they are in someway affiliated with or have participated in a local Java users group. I have blogged before about my appreciation of user groups and I have definitely benefited from the existence of Java users groups. In this post, I'll look at some concrete ways that participation in Java users groups has directly benefited me.

The most obvious Java users group that has been of benefit to me is the Denver Java Users Group (affectionately known as DJUG). DJUG typically holds one meeting per month with two technical sessions in each meeting. The two sessions are billed as "Main Meeting" and "Basic Concepts," but I have definitely attended when the "Basic Concepts" was every bit as important, useful, and informative as the "Main Meeting." I have always felt that my investment of time and effort to get to these meetings has been well rewarded.

A few years ago, when DJUG still met in the then-Qwest building on 17th and Curtis, I attended around over half the DJUG meetings for a while. It so happened they were covering many subjects of interest to me and the meetings fit my schedule fairly well. Unfortunately, since then increasing work and personal demands have made it more difficult to attend. I am still able to benefit from DJUG, however, thanks to their posting of presentations online in their archive and thanks to the blog posts of people who do attend.

I have definitely learned and re-learned/remembered some useful concepts from attending DJUG meetings. I have also been able to see and listen to speakers well-known in our industry. Many of them speak at major software development conferences, but there is a certain advantage to seeing them locally and in that environment. The cost (free) is also difficult to beat.

There are other local users groups as well that, although not Java-specific, are often useful to me. One example is the Rocky Mountain Oracle Users Group (RMOUG). Their meetings have covered several Java-related topics and products over the years.

I have also benefited from other non-local Java users groups. For example, there have been occasions when I have found a useful presentation on the NYJavaSIG site where they post some of their presentations.

How Java User Groups Benefit Java Developers

Java users groups can benefit Java developers in many ways. They obviously provide benefit by providing free or low-cost training, but they also provide benefits of regular meetings (throughout the year) and opportunities to meet and network with other Java developers. In addition, many Java users groups provide book reviews, newsletters, web sites, code samples, and other items that benefit Java developers.

Java Users Groups Are What Their Members Put Into Them

Any user groups, including those devoted to Java, depend on their users for success. The user groups need people to run the group (officers) as well as other types of volunteers and speakers. Even meeting attendees provide value to the user group by providing an audience, by asking good questions, and by answering each others' questions.

Characteristics of Successful Java Users Groups

The success of a Java users group is largely dependent on the base of involved and participating users. Large cities with large numbers of Java developers have an advantage here because a larger pool of Java developers often means a larger pool of enthusiastic Java developers to power the user group. Successful Java users groups tend to be run by energetic and enthusiastic individuals with a vested interest in sharing Java knowledge and learning more about Java and related topics.

What I've Learned from Java-Related User Groups

Here I list a few examples of some of the things I first learned or was exposed to thanks to a Java-related users group.

JMX - My first solid exposure to Java Management Extensions was at a 2004 DJUG meeting (during what was in many ways JMX's heyday) and via a Dr. Dobb's magazine article.

Ruby on Rails - David Geary's July 2005 DJUG presentation on Ruby on Rails was a big part of my learning and using Ruby on Rails.

• Software Development Methods - Al Davis's October 2006 presentation What's New About New Methods of Software Development? reaffirmed my belief that there is very little that is really all that new in software development and that most of the "new" processes and approaches are really just old ideas returning to fashion.

• Software Development Tools and Libraries - I have observed that I often learn about presenters' and attendees' favorite tools and libraries at user group meetings. In fact, it is often the mention of these new (to me) tools and frameworks that really makes me happy that I attended.

• Things Not to Use - I have attended user group meetings where the main thing I learned during the presentation was that I did not need to invest any more time in learning about the subject of the presentation. Although it is always fun to attend a meeting and learn about a new concept that I can apply quickly, it is just as worthwhile (albeit a little disappointing at the time) to learn about things that won't work for my situation or that I should not spend any more time on.


Conclusion

In the end, successful users groups rely mostly on peoples' time. It takes a few dedicated individuals to make it happen and many committed members to make it worth while. For developers willing to invest the time, users groups can be valuable sources of new information.

Java Collections Default Implementation Choices: Groovy's Opinion

I think many Java developers use the Java Collections Framework like I do: start with the same basic implementations of each of the major collections interfaces for general cases and only use a different implementation when there is a need that drives it (such as need for NavigableMap). For example, for a long time, I used ArrayList for Lists, HashSet for Sets, and HashMap for Maps. I have started to heavily use EnumSet and EnumMap for appropriate Set and Map situations respectively, but I still seem to have my same favorite "default" collections implementations.

Ruby on Rails in large part made "convention over configuration" popular and the Java Peristence API (JPA) further popularized this concept in the Java world under the name "configuration by exception." Of course, many other frameworks and libraries have similarly used and popularized the concept of reducing the need for explicit configuration when conventions and defaults are good enough. One of the appealing facets of Groovy is its support for certain collection types by default without explicit specification and only assumed from the syntax used. In this post, I look at the default implementations that the Groovy developers selected for the Groovy language to use when no specific implementation is specified.

Most introductory Groovy materials demonstrate (and often applaud) the conciseness and intuitiveness of Groovy's collections specification syntax. Much of this is a result of Groovy assuming which implementation of each collection will be used. Groovy does allow this default choice to be overridden by explicit specification of the desired collection implementation. The following code snippet demonstrates Groovy's default implementations for Lists, Sets, and Maps.


list = ["Denver", "Chicago", "Tallahassee", "Detroit", "Salt Lake City", "Las Vegas", "Atlanta"]
println "\nLIST: Default List implementation is ${list.getClass().name}\n"

map = ["Colorado" : "Denver", "Florida" : "Tallahassee", "Michigan" : "Detroit"]
println "MAP: Default Map implementation is ${map.getClass().name}\n"

set1 = list as Set
println "SET: Default Set implementation is ${set1.getClass().name}\n"

Set set2 = ["Colorado", "Florida", "Michigan", "Utah", "Nevada", "Georgia"]
println "SET: Default Set implementation is ${set2.getClass().name}\n"

queue = list as Queue
println "QUEUE: Default Queue implementation is ${queue.getClass().name}\n"


When the above script is run (as demonstrated in the next screen snapshot), we learn that the ArrayList is Groovy's default implementation of the List interface, that HashSet is Groovy's default implementation of the Set interface, LinkedHashMap is Groovy's default implementation of choice for the Map interface, and LinkedList is Groovy's default implementation of the Queue interface.



The authors of the book Java Generics and Collections compare the standardly supplied Java collections implementations in their book. They devote sections of their book (13.3/Sets, 15.3/Lists, 16.6/Maps, 14.5/Queues) to comparing different collections implementations for each interface (List, Set, and Map) and compare them based on comparative performance and functional requirements they satisfy. There are so many implementations and so many considerations facing one over another that it is difficult to choose one to "generally use," but the Groovy selections definitely seem reasonable based on the analysis contained in this book. One obvious exception to this is that the authors are critical (Section 14.4.1) of LinkedList as a Queue (or even Deque) implementation.

Conclusion

Groovy provides concise and highly intuitive syntax for some of its collections implementations, but must make certain assumptions about the particular collection implementation to do this. It is interesting to compare the default implementation choices for Groovy use of collections interfaces to my own default choices. Of course, when in a concurrent environment or facing certain other unique circumstances, the idea of a "general" collection implementation doesn't apply anymore anyway. Certain collections implementations may also be favored for different types of operations on the collection.

Saturday, November 21, 2009

Using Groovy to Check Seventh Grade Homework

Using Groovy to Calculate Volume and Surface Area of a Cylinder

I have recently been involved in checking a seventh grader's math homework to make sure it was done correctly and to help her learn the new concepts. The recent focus of her class has been on volumes and surface areas of various geometric shapes. These can be tedious to check the arithmetic on. Although I do have a HP48GX calculator (my HP48SX got stolen about 3/4 of the way through my degree) from the days of my undergraduate degree in electrical engineering, its built-in formulas use a definition of pi with many more significant digits than the seventh graders use (3.14). There are other options available (such as Google search's online calculator function), but the potentially different precision of PI is still an issue.

For a variety of reasons (inner geekiness, long-term laziness, and because I can use it as a blog topic) I decided to write a small application to make these checks easier. I did not want to directly deal with floating-point arithmetic issues and Java's handy BigDecimal came to mind. At about the same time, I realized that this was a perfect use for Groovy: I wanted a Java language feature but wanted to be able to write concise, script code.

The volume (V = Πr2h) and surface area (SA = 2Πr2 + 2Πrh) of a cylinder are the main topics for the current homework assignment. The Groovy code below calculates the volume and surface area of a cylinder given a radius as the first parameter and a height as the second parameter. It is assumed that the radius and height are in the same (unspecified) units.


// cylindrical1.groovy
//
// Calculates geometric characteristics of a cylinder with given radius and height.
//

// Don't want to use Math.PI because want same accuracy as used in homework
pi = 3.14

radius = new BigDecimal(args[0])
height = new BigDecimal(args[1])

volume = pi * radius * radius * height
surfaceArea = 2 * pi * radius * radius + pi * 2 * radius * height

println "Volume of cylinder with radius ${radius} and height ${height} is ${volume}."
println "Surface area of cylinder with radius ${radius} and height ${height} is ${surfaceArea}"


Running the script on several different values for radius and height of different cylinders is shown in the next screen snapshot.



The script above does the job, but it can be improved even more. In the second version of this script, I add a conditional check that prints out usage information if the caller does not provide two numeric values for radius and height. I also use Groovy's GDK-extended String method toBigDecimal() rather than the more traditional approach of passing the String to the BigDecimal constructor.


// cylindrical2.groovy
//
// Calculates geometric characteristics of a cylinder with given radius and height.
//

if (args.length < 2)
{
println """You must enter at least two numeric parameters for radius and height.
Usage: cylindrical2 <<radius>> <<height>>"""
System.exit(args.length)
}

// Don't want to use Math.PI because want same accuracy as used in homework
pi = 3.14

radius = args[0].toBigDecimal()
height = args[1].toBigDecimal()

volume = pi * radius * radius * height
surfaceArea = 2 * pi * radius * radius + pi * 2 * radius * height

println "Volume of cylinder with radius ${radius} and height ${height} is ${volume}."
println "Surface area of cylinder with radius ${radius} and height ${height} is ${surfaceArea}"


The "happy path" output for this version of the script is the same as for the first version and will not be shown here. However, the usage information provided when an insufficient number of parameters is provided is shown in the next screen snapshot.



One problem still remaining with this script is that non-numeric values passed in for radius or height can be problematic as demonstrated in the next screen snapshot in which the second command-line argument (expected height) is a String.



One approach for dealing with this is to use the GDK-extended String method isNumber(). This is the approach applied in the next Groovy code listing.


// cylindrical3.groovy
//
// Calculates geometric characteristics of a cylinder with given radius and height.
//

if (args.length < 2 || !args[0].isNumber() || !args[1].isNumber())
{
println """You must enter at least two numeric parameters for radius and height.
Usage: cylindrical2 <<radius>> <<height>>"""
System.exit(args.length)
}

// Don't want to use Math.PI because want same accuracy as used in homework
pi = 3.14

radius = args[0].toBigDecimal()
height = args[1].toBigDecimal()

volume = pi * radius * radius * height
surfaceArea = 2 * pi * radius * radius + pi * 2 * radius * height

println "Volume of cylinder with radius ${radius} and height ${height} is ${volume}."
println "Surface area of cylinder with radius ${radius} and height ${height} is ${surfaceArea}"


The improved output now resulting from the providing of a non-numeric value for height is shown in the following screen snapshot.



Although this basic command-line argument checking is not difficult, it turns out that Groovy has more sophisticated command-line argument support built in. Groovy takes advantage of the Apache CLI library that I have previously blogged on and makes it even easier to use via CliBuilder. The next code listing demonstrates Groovy code using CliBuilder to handle command-line arguments. In addition, it provides several other examples of additional "grooviness."


#!/usr/bin/env groovy
// cylindrical4.groovy
//
// Calculates geometric characteristics of a cylinder with given radius and height.
//

def cli = new CliBuilder(usage: 'cylindrical -r radius_arg -l height_arg [-u arg]')
cli.with
{
h(longOpt: 'help', 'Usage Information')
r(longOpt: 'radius', required: true, type: Number, 'Radius of Cylinder', args: 1)
l(longOpt: 'length (height)', required: true, type: Number, 'Height of Cylinder', args: 1)
u(longOpt: 'units', 'Units of Supplied Radius and Height', args: 1)
p(longOpt: 'pi', 'Value of pi used in calculations', type: Number, args: 1)
}
def opt = cli.parse(args)
if (!opt || opt.h) return // parsing error occurred or usage was requested
if (!opt.r.isNumber()) {println "Radius must be numeric."; cli.usage(); return}
if (!opt.l.isNumber()) {println "Height must be numeric."; cli.usage(); return}

def radius = opt.r.toBigDecimal()
def height = opt.l.toBigDecimal()
def printableUnits = opt.u ?: "units" // "Elvis" operator
def pi = opt.p ? opt.p.toBigDecimal() : Math.PI

// Don't want to use Math.PI because want same accuracy as used in homework
//def pi = 3.14

def volume = pi * radius * radius * height
def surfaceArea = 2 * pi * radius * radius + pi * 2 * radius * height

println "All calculation are using ${pi} as the value of 'pi'"
println "Volume of cylinder with radius ${radius} ${printableUnits} and height ${height} ${printableUnits} is ${volume}."
println "Surface area of cylinder with radius ${radius} ${printableUnits} and height ${height} ${printableUnits} is ${surfaceArea}"


The use of Groovy's built-in support for command-line argument via Apache CLI and CliBuilder facilitates easy development of command line options with short (single hyphen) and long (double hyphen) names. Usage information is readily available via CliBuilder as well. In the code above, I used Groovy's with() to group the calls on my "cli" object.

Because CliBuilder is so easy to use, I threw in two more options to make the script output potentially more interesting and flexible. I also have support for radius and height to be more specifically specified so there is less change of switching the two numeric values on accident. The new command-line options allow the user to optionally specify the units of measurement and the value of PI used. If the units are not specified, the string "units" is used (thanks to the Elvis operator) and if the value of PI is not specified, the value from Math.PI is used by default (thanks to traditional Java's ternary operator).

The next screen snapshot demonstrates the flexibility of this final version of the script for calculating cylindrical volume and surface area.



As the screen snapshot above demonstrates, CliBuilder has allowed me to easily apply great flexibility and usefulness in the my script. Other online posts on Groovy and CliBuilder include Groovy CLIBuilder in Practice, Groovy Command Line Options, Groovy CliBuilder with Multiple Arguments, and Groovy Script: Get SSL Cipher and CLIBuilder Example.

Observations

Groovy Uses of Standard Java APIs and Third-Party Java APIs and Libraries

One of the compelling advantages of Groovy is readily usable Java libraries and APIs and Groovy's built-in use of Apache CLI is a great example of this. For example, if the built-in, Apache CLI-powered command line arguments handling is not exactly what you want, you could consider using another Java-based library such as Args4j. For a direct Groovy alternative to the built-in support using Apache CLI, consider Groovy Option Parser. Java's BigDecimal (which Groovy uses underneath the covers for floating point types by default) was also particularly useful in this example.

Groovy is Great for Scripting

Groovy brings the advantages of Java's rich feature set while at the same time allowing the scripts to be written more script-like.

Programmer Laziness is a Different Type of Laziness

As many blog posts have already pointed out, the "lazy" programmer is often not "lazy" in the traditional sense of the word. The "lazy" programmer tends to go out of his or her way to reduce the tedious tasks that he or she must perform. He or she may be willing to expend significant effort to generate a script to avoid tedium that might, especially in an isolated case, take less time than writing the script. However, if the situation is one that is repeated, the generated script should earn back its time spent many times over.

Conclusion

Groovy is the perfect fit for writing a simple script to perform floating-point arithmetic with precise desired precision. I actually used the first version of the script in my case because it was done in about five minutes, but it was fun to make it more elegant and present that here. Another observation from all of this might be developers' strange sense of "fun." Groovy gives me a scripting language with the language richness and features of Java.

Friday, November 20, 2009

Java 7: The Return of Closures

The Big Announcement: Closures in JDK 7!

The biggest current news in the Java world is the apparent reconsideration by Sun regarding the addition of closures to JDK 7. Mark Reinhold's Devoxx announcement has led to many posts on the subject including Stephen Colebourne's Closures in JDK 7, Alex Miller's Closures After All?, Ted Neward's Closures Are Back Again, Cay Horstmann's Closures? In Java 7???, Mitch Pronschinske's Closures Coming to Java 7, Geertjan Wielenga's Devoxx Day 3: Conference Day 1, and a summary of some of these posts in the Java.net editorial DEVOXX Surprise: Out of Nowhere: Closures in JDK 7!

The collective excitement, concern, confusion, and questioning attitudes represented by these posts is likely indicative of the general Java community's feelings regarding this announcement. I have blogged before regarding closures being (at that time we thought based on last year's Devoxx announcement) one of the most-missed features to not be included in Java 7. Dionysios G. Synodinos summarized, in Java 7 Roadmap Updated: Reactions, several online reactions (including mine) to the 2008 Devoxx announcement that closures were being omitted from JDK 7. The Java.net poll on most-missed Java 7 features showed closures being the most voted for "missed feature" with nearly half the votes. Even James Gosling has weighed in with his favoring of closures in Java. The JSR Proposal for Closures in Java also lists individuals and organizations particularly interested in Java closures. Closures are clearly popular with Java developers who read and write regularly in the blogosphere.


What Are Closures?

For those who are not familiar with closures, Martin Fowler's post Closure is perhaps the definitive explanation of what constitutes a closure. Fowler states about closures: "Essentially a closure is a block of code that can be passed as an argument to a function call." Fowler compares and contrasts closures with anonymous classes and highlights closures as syntactically simpler than anonymous classes and able to see variables available at time of closure definition.

Besides Fowler's Closure post, other useful introductions to closures can be found in the Groovy User Guide section on Closures (defines closures as "A Groovy Closure is like a 'code block' or a method pointer.") and in the Wikipedia entry on closures.


What Are the Java Closure Proposals?

The JavaWorld article Understanding the Closures Debate lays out the three most popular proposed alternatives for closures in Java. The three primary proposals for Java closures are BGGA, CICE, and FCM.

The BGGA proposal is named after the first letter in the last names of each of its original authors: Gilad Bracha, Neal Gafter, James Gosling, and Peter von der Ahe. It is often referred to as the "full closures" proposal and was by far the most popular of the three options voted on in this Java.net poll.

The FCM (First Class Methods) closure proposal is the one closest to the example syntax Mark Reinhold reportedly wrote on the airplane ride to Devoxx and it sounds like FCM 0.5 is considered the starting point for Java 7 treatment of closures. It currently sounds like the Java 7 implementation would exclude inclusion of the Java Control Abstraction (JCA) features.

A third Java closures proposal is the Concise Instance Creation Expressions (CICE) proposal by Josh Bloch, Doug Lea, and Bob Lee proposes "a more concise syntax to instantiate anonymous classes." Bob Lee's introduction of CICE closure proposal compares it to the BGGA proposal. Elliotte Rusty Harold has posted his complaints about the CICE proposal.

The blog post Comparing Inner Class/Closure Proposals compares the three above proposals and throws the Clear, Consistent, and Concise (C3S) for Java proposal into the comparison.


Additional Resources

Another good resource regarding Java and closures is Brian Goetz's The Closures Debate. The Closures Syntax in Java 7 Twiki page and Alex Miller's Java 7 page have numerous links to additional information on closures in Java.

Monday, November 16, 2009

Groovy Console: Graphical Groovy Shell

I wrote about Groovy Shell in my last blog post. As I wrote in that post, Groovy Shell is a highly useful command line based method for experimenting with Groovy code. For those who prefer a graphical interface over the command line interface, Groovy Console provides a nice alternative and that is the subject of this blog post.

Assuming Groovy is appropriately installed on one's system with GROOVY_HOME defined correctly, it is easy to run the Groovy Console by simply typing groovyConsole at the command line. The next screen snapshot shows the running of Groovy Console along with the output from selecting Help->About.



It is easy to enter Groovy code and execute it (by clicking on the icon on the far right with the green arrow pointing right). The next two screen snapshots show entering Groovy code in the top pane and then the results of clicking on that "Execute Groovy Script" button in the bottom pane. Color coding helps make the scripts and the output more readable.





The Groovy Console supports larger fonts. The next screen image shows the results of selecting View -> Larger Font multiple times.



This image also shows a simple script for getting the date/time from Calendar using Groovy's property access syntax. Instead of needing to call getInstance() on Calendar and getTime() on the returned Calendar instance, I was able to access those directly with .instance.time.

Groovy Console allows one to select whether shortened or full stack traces should be displayed. The following two screen snapshots demonstrate the difference between the normal (shortened) stack traces and full stack traces. To turn on full stack traces, one selects View -> Show Full Stack Traces.





In this case, it is easy to deal with the stack trace. All that needs to be done is to import the Color class as shown in the next screen snapshot (classes in java.awt package are not automatically imported in Groovy).



Groovy Console supports numerous other useful features. Scripts can be saved to disk once they do what the developer wants. JAR files and directories can be added to the Groovy Console classpath for custom Java classes used by Groovy scripts. The Groovy Console page lists many more useful features of Groovy Console such as the ability to host Groovy Console as an applet and the ability to embed Groovy Console in Swing-based applications.

Another useful graphical approach to playing with Groovy code is the Groovy web console deployed on Google App Engine.

Groovy Shell: A Gentle Introduction to Groovy

Groovy Shell brings to Groovy what irb (Interactive Ruby) and jirb (Interactive JRuby) bring to Ruby and JRuby respectively. I have written about both IRB and JIRB and in this blog post I look more closely at Groovy Shell.

As IRB and JIRB do for Ruby and JRuby, Groovy Shell provides an easy, command line based interactive tool for experimenting with Groovy syntax. This can be easier to use for experimenting with Groovy than writing files to be run in a separate step or trying to pass multiple commands to the Groovy interpreter with the -e option.

Assuming that Groovy has been appropriately installed, it is easy to run Groovy Shell with the groovysh command. Doing so leads to the output shown in the next screen snapshot.



Entering "help" at the Groovy Shell prompt brings up usage information as demonstrated in the next screen snapshot.



At this point, I'll demonstrate via Groovy Shell capabilities that Groovy applies similar to capabilities I demonstrated previously for Ruby and JRuby using IRB and JIRB. The next screen snapshot demonstrates some Groovy math operations in Groovy Shell.



Groovy provides many String operations one might not expect in a language as tied to Java as Groovy is. However, the next screen snapshot proves some of Groovy's string operations that behave similarly to those demonstrated for Ruby and JRuby in my previous writings on IRB and JIRB.



The 2004 JavaOne conference presentation The Groovy Programming Language: Let's Get Groovy includes a nice tip related to use of Groovy Shell. In one of that presentation's slides, Rod Cope and James Strachan demonstrated using Groovy Shell to easily determine the methods available on a particular class. They specifically looked at the File class, but it could be used on any class as shown in the next screen snapshot with File and String.



There is much more that can be done with the Groovy Shell and more information is available in the online Groovy User Guide section Groovy Shell. Some problems previously encountered with Groovy Shell are covered in the Troubleshooting section.

For those who prefer a graphical tool similar to Groovy Shell, the Swing-based Groovy Console or Google App Engine powered browser-based Groovy Web Console is likely to be of great interest.

Thursday, November 5, 2009

RMOUG Training Days 2010 Agenda

An early version of the agenda for RMOUG Training Days 2010 is now available. The agenda currently shows six University Sessions, ten 90 minute sessions, ten 30 minute sessions, and then many of the typical 60 minute sessions. As usual, many of the presentations are focused on Oracle database development and administration. However, there are several presentations likely to appeal to those who have little or no interest in the database.

The following are some of the sessions that I think look interesting based on their titles and abstracts. There are more attractive sessions than I will list here.

There is only one session (Session 4, Wednesday, 17 February 2010, 2:45 pm - 3:15 pm) with 30 minute presentations, but there are many potentially interesting presentations during that session. These include Using SQL to Generate SQL (likely to be particularly useful for those new to SQL), Java 6 and Java 5 New Features (likely to be particularly useful for those new to J2SE 5 or Java SE 6), and 10 Things I Did Not Learn from SQL Class (very specific how-tos listed in this abstract).

Bill Jackson's 60-minute presentation 10 Easy Ways to Build a Better Graphic User Interface is scheduled for Session 7 (Thursday, 18 February 2010, 9 am - 10 am). My first presentation, RESTful Java is scheduled for Session 8 (Thursday, 18 February 2009, 10:15 am - 11:15 am) and Oracle Fusion Design Fundamentals is offered in that same session. My second presentation, Applied Groovy: Scripting for Java Development, is scheduled for Session 11 (Thursday, 18 February 2009, 2:45 pm - 3:45 pm).

There are multiple presentations on Service Oriented Architecture (SOA) including SOA Today during Session 9 (Thursday, 17 February 2009, 11:45 am - 12:45 pm). Other SOA presentations include Problems and Solutions Facing SOA Implementations and Using Agile Approaches and Techniques for Rapid SOA Implementations (both Session 11) and Agile SOA: Is It Possible? (Session 7).

Although Oracle is pursuing acquisition of Sun Microsystems, Java and Sun products play a relatively minor role at Training Days 2010. There are three presentations with "Java" in the title, which are my two presentations ("RESTful Java" and "Applied Groovy: Scripting for Java Development") and the above-cited John King presentation "Java 6 and Java 5 New Features." There are additional presentations that are Java-related such as presentations on Application Development Framework (ADF) and Fusion.

Several of the speakers scheduled for RMOUG Training Days 2010 are very well-known in the Oracle community. These include Robert Freeman, Steven Feuerstein, and Duncan Mills. There are also several speakers who frequently present at RMOUG Training Days as well as some speakers that are new to Training Days.

I always start to get more excited about attending a conference once its agenda has been posted. I am looking forward to presenting at and attending RMOUG Training Days 2010.

Monday, November 2, 2009

Realizing That I Still Have Much to Learn

Several years ago, I was asked to rate myself on my level of expertise with different programming languages and frameworks. Several people were surprised when I did not rank myself at the highest possible level for knowledge of Java, especially when several developers with far less software development in general and far less Java experience in particular rated their own Java skills at the maximum level. I explained to them that I too would have at one time ranked myself at the highest possible level but that I had learned enough since that time to realize how much I still needed to learn. There was no way I could in good conscience rate myself at the highest level knowing how many areas of the Java ecosystem I lacked experience and depth of knowledge in. I believe there are numerous advantages to always understanding what one doesn't know (or working to discover what one doesn't know) and will outline some of these advantages in this post.


Ability to Consider New Options

When one thinks he or she already knows everything, that person has no incentive or interest in considering anything new or different than what he or she has done before. This can backfire because the same solution or approach rarely fits every problem a developer will encounter. It might seem easiest to shoehorn a particular problem into the solution we know best, but that does not make it the best or even an appropriate solution. By admitting that I may not know everything and have much still to learn, I will be more willing to listen to others' ideas and consider other perspectives. I still may end up going with my initial solution, but I will have thought out its benefits and costs and weighed them against the benefits and costs of the alternatives.


Ability to Learn New Things

If I think I know everything already, I have no need to waste time learning anything new. Learning new things can be tiring and even frustrating, but I am more apt to invest the time and effort in my own knowledge if I realize that there is so much still to learn.


Ability to Challenge My Own Assumptions and Biases

The person who knows everything (or at least thinks he or she is omniscient) has no reason wonder if what he or she is doing is correct for a given situation. The person who understands that he or she doesn't know everything is more willing to question his or her own actions and measure the results of those actions. If a course change is necessary, the person who understands his or her limitations is more likely to identify that need and do something about it. I have written before about the importance of confidence to a software developer. I think confidence is one of the most important traits of a successful software developer, but true confidence (as opposed to arrogance) does not preclude one from understanding that he or she is not necessarily always correct.


The Cost of Not Realizing There is Much More to Learn

I have seen many individuals who believe they have all the answers and make silly statements or, even worse, make unnecessarily costly decisions because of their arrogance and lack of understanding of their own limitations. By not having at least an idea of what one doesn't know, one is not able to sufficiently consider other ideas, to question the correctness of one's own decisions, and to realize the importance of learning new things.


The More We Learn, the More We Realize That We Don't Know

I have found that the more I learn and understand a particular subject, the more I realize how much more I still have to learn. It seems that I can only understand the bigger picture of a language or framework once I have begun to understand specific details of that language or framework. As I immerse myself in a new language or framework, I'm more likely to notice relevant articles posted on DZone or Reddit. Better yet, the more I learn about something, the more these blogs and articles make sense to me and the bigger the possibilities become.

As an example of this principle, consider a person learning the Java programming language. He or she may at first think only of the programming language itself and focus on keywords, syntax, and so forth. As the person gains familiarity with Java SE, he or she may start to be more exposed to Java EE principles. Similarly, the developer may start to learn about other languages on the JVM. In addition, that developer may start to learn about frameworks and libraries available for use. During all this, that developer continues to learn the Java APIs and how vast they are. What seemed like a simple language turns out to be a complex, ever-changing ecosystem.

The interesting phenomenon here is that because I have repeatedly realized how much more I still have to learn after I have learned substantially new information, I assume that I will continue to realize that I have even more to learn as I continue to learn and gain experience. In other words, the absolute amount of knowledge I would like to learn to be more effective is likely to only get larger, even as I learn new things. It's not that I realize that I need to learn more despite my current learning; rather it's precisely because I'm learning that I realize how much more I still need to learn.


Conclusion

When one understands that he or she may not be always correct, he or she is more likely to catch their own mistakes early before they are most costly, is more likely to listen to and seriously consider alternative approaches, and is more likely to keep bettering himself or herself. I am realizing that it is actually a good sign when I understand how much I still have to learn -- this often means that I'm starting to get a much better understanding of the big picture and how things fit together.