Java Magazine Logo
Originally published in the July/August 2014 issue of Java Magazine. Subscribe today.

Performing 10 Routine Operations Using Different JVM Languages

by Venkat Subramaniam

Published July 2014

JVM languages offer unique capabilities, powerful constructs, and specialized libraries.

Daily coding activities are often punctuated by several routine operations, from reading a file to processing XML documents. Performing these operations with ease, using just a few lines of code, can help get those tasks out of our way, so we can focus on more-important, application-specific tasks.

In this article, we will use a polyglot approach to look for elegant, concise solutions for performing routine tasks using different Java Virtual Machine (JVM) languages.

Note: The source code for the examples described in this article can be downloaded here.

Leveraging the Polyglot Ecosystem

In the past few years, the JVM platform has flourished with quite a few powerful languages. Many developers have made use of different languages to program on the JVM. Each day, I come across more developers who are curious, willing, and eager to learn and apply techniques and solutions from different languages.

The different languages on the JVM do not merely offer a different syntax. Each of them comes with unique capabilities, a few powerful constructs, or specialized libraries that can make some routine tasks easy or almost trivial to perform. For example, Groovy’s metaprogramming capability or Scala’s ability to handle XML as a first-class citizen can come in handy. Furthermore, some things that were rather onerous in Java before just got easier with the recent release of Java SE 8.

In this article, we will explore solutions from Groovy, Scala, and Java SE 8 for the following operations:

  • Quickly reading a file (Groovy and Scala)
  • Easily starting a process (Groovy)
  • Joining values (Java SE 8)
  • Using delegation over inheritance (Groovy)
  • Performing pattern matching (Scala)
  • Easily parsing XML (Groovy)
  • Generating XML documents (Groovy)
  • Creating expressive code (Groovy)
  • Making deep recursion possible (Scala)
  • Guaranteeing resource cleanup (Java SE 8)

To try out the provided examples in a specific language, ensure the latest version of the language is installed on your system and the PATH environment variable is set up appropriately.

Quickly Reading a File Using Groovy and Scala

Let’s take a look at the effort needed to read the entire contents of a small file using Java.

Tasks that are arduous in one language might be quite easy to perform in another.

In Listing 1, we first open the /etc/networks file using the BufferedReader class (replace /etc/networks with a filename that is valid for your system). Then we loop through each line to concatenate the content into a StringBuilder. The noise in the code comes from two parts: the lack of a convenience method in BufferedReader and the need to handle checked exceptions. We can reduce the noise just a bit by using the BufferedReader’s lines() method in Java 8; however, the noise from checked exceptions is here to stay.


public class ReadFile {
  public static void main(String[] args) {
    try {
      BufferedReader reader = new BufferedReader(
                                                         new FileReader("/etc/networks"));

      StringBuilder fileContent = new StringBuilder();
      String line;
      while((line = reader.readLine()) != null) {
        fileContent.append(String.format("%s%n", line));

      //use fileContent for something practical here... 
    } catch(FileNotFoundException ex) {
    } catch(IOException ex) {

Listing 1

We can quickly read the entire contents of a relatively small file using one line of code in both Groovy and Scala. Let’s take a look at an example in Groovy first.

In Listing 2, File is the all-too-familiar class from the JDK package. Groovy has extended this class with a getText() method, which we can access using the text property. Furthermore, Groovy does not have checked exceptions, so we’re not forced to handle any exceptions. (Any exception we don’t handle will propagate much like unchecked exceptions do in Java.)

def fileContent = new File('/etc/networks').text

Listing 2

To run the code shown in Listing 2, type the following command on the command line, where readFile.groovy is the file in which the Groovy code is saved:

groovy readFile.groovy

In case we mistype the filename, we can place a try and catch block around the code, if we desire, to handle any exceptions such as “file not found.” Replace the constructor argument /etc/networks with other filenames to get the contents of different files.

Let’s take a look at similar code in Scala. In Listing 3, the fromFile() method of the Source class can read the entire content of a given file and return an iterator. The mkString method concatenates the lines into a single string. Instead of using this method, we could iterate over each line, processing one line at a time.

val fileContent ="/etc/networks").mkString
//use fileContent for something practical here...

Listing 3

To run the code in Listing 3, type the following command on the command line, where readFile.scala is the file in which the Scala code is saved:

scala readFile.scala


Easily Starting a Process Using Groovy

On a project I was working on, I was able to replace 50 lines of code for starting and interacting with an external program with a mere three lines of Groovy code, thanks to some convenience methods in Groovy.

In the previous section, we saw how Groovy took the File class and extended it with a convenience method. Likewise, Groovy adds some convenience methods to the java.lang.Process class, which we can use to easily start external processes.

Let’s take a look at an example to call an external program. To keep the output short, we will simply call git but ask only for the version number. Listing 4 shows the code.

println "git version".execute().text

Listing 4

To run an external process, we first create a string of the command we want to run, such as git version in this example. Then we call the execute() method on it. This is a Groovy-created extension method on the java.lang.String class. This method returns a java.lang.Process instance on which we call the get Text() method (using the text property). This method returns the standard output of the program we invoked.

To run the program, save it in a file named callGit.groovy and type the following command on the command line:

groovy callGit.groovy

Here’s the output from the code:

git version 1.9.2

In this example, we merely printed the content from the standard output. However, by storing a reference to the result of the execute() method, we can attach to standard input and standard error if we want more control over the interaction with the external process.

Joining Values Using Java SE 8

Given a list of names, let’s look at the effort that is required to print the values in comma-separated format (see Listing 5).

import java.util.*;

public class PrintList {
  public static void main(String[] args) {
    List<String> names = Arrays.asList(
       "Marlin", "Gill", "Greg", "Deb", "Bruce");


Listing 5

Let’s compile and run the code in Listing 5 from the command line:

java PrintList

Here is the output from the code:

[Marlin, Gill, Greg, Deb, Bruce]

It’s not quite what we wanted; the names are comma-separated, but we have to get rid of those square brackets. Let’s try again using the code in Listing 6, which uses the Java SE 5 for-each construct to loop through the values and print them in comma-separated form. Now we get this output:

    for(String name : names) {
      System.out.print(name + ", ");

Listing 6

Marlin, Gill, Greg, Deb, Bruce,

We got rid of the square brackets, but there is a silly comma at the end. This simple task seems to be a slippery slope. Let’s take yet another stab at it, this time to get rid of that trailing comma (see Listing 7).

    for(int i = 0; i < names.size(); i++) {
      if(i != names.size() - 1) System.out.print(", ");

Listing 7

Here is the output of this version:

Marlin, Gill, Greg, Deb, Bruce

That worked! But, all of us have gone through similar exercises and ended up with code that we wouldn’t be proud to flaunt. Such experiences leave us wondering why such a simple task should be so difficult to do.

Thankfully, the way we do this task has changed in Java SE 8. The String class has a new join method that can save us from all this trouble. Listing 8 makes use of this new method.

    System.out.println(String.join(", ", names));

Listing 8

With one call to the join method, we instructed Java to concatenate the elements in the list into a single string. We went from the verbose version that had a primitive obsession to a declarative version in which we concisely specified our intention. If we want to perform some operations on the list of elements and then concatenate the result, we can use the joining method of the Collectors utility class with the collect method of the Stream interface.

Java SE 8 added a number of similar new convenience methods to the classes and interfaces in the JDK to make our lives easier. Take a few minutes to revisit the JDK classes and interfaces to see what’s new in Java SE 8.

Using Delegation in Groovy

Inheritance is quite useful for substitutability when an instance of a class can be used in place of an instance of a base class. However, if we desire class reuse more than substitutability, it is better to use delegation instead of inheritance.

Yet, in Java we often use inheritance more than delegation. The fact that delegation is difficult to write while inheritance is easy to implement is one of the reasons. If delegation were just as easy, we might rely on it more.

Using compile-time metaprogramming, Groovy makes delegation quite easy to use. Let’s look at an example. The two classes in Listing 9 are written in Groovy; however, they could be written in any JVM language.

class Worker {
  void work() {  println 'working...' }

class Analyst {
  void work() {  println 'analyst working...' }
  void analyze() {  println 'analyst analyzing...' }

Listing 9

The Worker class has one method, work, which prints out a message when called. The Analyst class has two methods, one with the same name and signature as the method in the Worker class.

Let’s now create a Groovy class named Boss, which—as you might expect—does nothing. However, this is one smart class; it knows how to tactfully delegate (see Listing 10).

class Boss {
  @Delegate Worker worker = new Worker()
  @Delegate Analyst analyst = new Analyst()

Listing 10

Within the Boss class, we first use the @Delegate annotation on an instance of the Worker class. This tells the Groovy compiler to generate in the Boss class a method named work that merely routes the call to the same method of instance worker. Then we use the annotation again, this time on an instance of Analyst, which instructs the compiler to bring in methods from the Analyst class that are not already in the Boss class. Since the compiler just synthesized the work method, it skips that method of the Analyst class and generates a delegation method for the analyze method.

Let’s use the Boss class now:

def boss = new Boss()


We created an instance of Boss and invoked the methods work and analyze. Before we run this code, let’s take a look at the compiler magic. Save the Worker class, the Analyst class, and the Boss class plus the code above for using the Boss class in a file named delegate.groovy. Then, as shown below, compile the file using the groovyc compiler, which will produce Java bytecode for the three classes:


groovyc delegate.groovy

Let’s take a peek at the bytecode for the Boss class using the javap tool:

javap -c Boss.class

If you examine the output of this tool, you will find that the compiled Boss class contains a method named work where the implementation routes the call to the worker instance’s work method. See the excerpt shown in Listing 11.

Compiled from "delegate.groovy"
public class Boss implements groovy.lang.GroovyObject {

  public void work();
       0: aload_0
       1: getfield      #29                                                  // Field worker:LWorker;
       4: invokevirtual #45                                           // Method
       7: aconst_null
       8: pop
       9: return

Listing 11

Likewise, the analyze method will route the call to the analyze method of the analyst instance.

Run the delegate.groovy file from the command line:

groovy delegation.groovy

Here is the output from the code:

analyst analyzing...

Groovy has a number of annotations such as @Delegate that perform compile-time abstract syntax tree (AST) transformations. Since these are done at compile time, there is no overhead at runtime for using these features. So, they provide convenience without compromising runtime performance.

Performing Pattern Matching in Scala

There’s often a need to parse the content of a file or content received through a messaging service. The pattern matching capability of Scala is one of my favorite features of the language. It provides a concise way to not only take actions based on the types of data, but also to extract the contents from select types. Let’s look at the example shown in Listing 12.

def process(message : Any) = {
  message match {
    case str: String => println(s"String: $str")

    case 5 => println("high five")

    case n: Int => println(s"number: $n")

    case List("apple", "peach",  fruits @ _*) =>
   s"Received apple, peach with ${fruits.mkString(", ")}") 
    case <greet>{msg}</greet> => println(s"$msg XML")

Listing 12

The process method receives an object (Any in Scala is like Object in Java). We invoke the match method on the instance and provide it several case statements to match against. In the first case, we look for an instance of String. If that match does not succeed, Scala will continue looking further in the sequence. We then look for the literal 5 followed by any instance of Int.

In the next case, we look for a list that starts with two elements: apple and peach. We capture the remaining elements in a fruits variable and print it comma-separated using the mkString() method (this method is the Scala equivalent of the Java SE 8 joining method we discussed earlier).

In the final case, we look for an XML fragment and parse the child of the greet element. In each of the case matches, we print a message with details about the parsed content.

As an aside, in Listing 12 we see how Scala treats XML as a first-class citizen. We can place any well-formed XML directly into Scala code, and we can embed Scala expressions into XML for easy generation of XML documents.

Let’s call the process method with a few different values, as shown in Listing 13.

process(List("apple", "peach", "grapes", "kiwi"))
try {
} catch {
  case ex : MatchError => println(s"Error: $ex")

Listing 13

Now, let’s look at the output first and then discuss each of the calls. To run the code, save the code in Listing 12 and Listing 13 in a file named match.scala and then type the following on the command line:

scala match.scala

Listing 14 shows the output.

String: hello
high five
number: 2
Received apple, peach with grapes, kiwi
howdy XML
Error: scala.MatchError: 2.2 (of class java.lang.Double)

Listing 14

The call to process with hello as an argument was picked up by the first case since there was a direct type match. The second call with a value of 5 was matched by the literal in the second case. The argument of 2, on the other hand, was matched by the case with the Int type. The List argument was matched by the case with the list, and the fruit variable was bound to the values grapes and kiwi.

Further, the XML fragment we passed in was matched by the last case and the child of the greet element, howdy, was bound to the msg variable. The last call with argument 2.2 was unmatched since no case exists for that value or that type. Therefore, the last call generated a runtime MatchError exception, which we handled on the call side.

In applications where we want to match against different types, values, or both, we can make use of the Scala matching capability to succinctly compare and process the values.

Easily Parsing XML Using Groovy

Groovy’s XmlSlurper, combined with the dynamic nature of the language, makes parsing XML documents effortless. Let’s get a feel for its capabilities using an example XML document, languages.xml, which is shown in Listing 15.

  <language name='C++'>
  <language name='Java'>
  <language name='Scala'>
  <language name='Ruby'>
  <language name='Lisp'>

Listing 15

The root element, languages, has a bunch of child elements named language. Each of the child elements contains a name attribute and an author child element. Let’s use the code in Listing 16 to parse this XML content and print the name and author of each of the languages mentioned in languages.xml.

def languages = new XmlSlurper().parse('languages.xml')

println "Languages and authors:"

languages.language.each {
  println "${it.@name} \t ${[0]}"

Listing 16

Listing 16 creates an instance of the XmlSlurper and points its parse method at the languages.xml file. The parser creates an instance of a node representation. We can dynamically access the properties of this object using the names of the known elements in languages.xml. To access an attribute, we prefix the name of the attribute with the @ symbol, for example, @name.

By looking beyond the syntax—by exploring the libraries and key capabilities of the languages we adopt—we can leverage the languages to perform various routine tasks with greater ease.

Let’s run this code and take a look at the output it produces:

Languages and authors:
C++              Stroustrup
Java             Gosling
Scala            Odersky
Ruby             Matz
Lisp             McCarthy

In addition to simple iteration over the elements, we can also apply powerful filter and search operations to extract the desired contents or parts of the document.

Generating XML Documents Using Groovy

In the previous section, we saw how to parse an XML document using Groovy. Groovy also makes it quite easy to create an XML document from data in memory (or data read from a file or from a database). Let’s create a hashmap with sample data for languages and authors, and then create code to produce the languages.xml file we used earlier.

In Listing 17, the langs reference holds a hashmap of some languages as keys and their authors as values. The code creates an instance of groovy.xml.MarkupBuilder and uses the variable builder to hold a reference to it.

def langs = ['C++' : 'Stroustrup', Java : 'Gosling', 
  Scala : 'Odersky', Ruby : 'Matz', Lisp : 'McCarthy'] 
def builder = new groovy.xml.MarkupBuilder()

builder.languages {
  langs.each { key, value ->
    language (name: key) { author(value) }

Listing 17

MarkupBuilder provides a highly fluent interface—with syntax similar to a domain-specific language (DSL)—for creating XML documents. If we call a property on an instance of MarkupBuilder and MarkupBuilder does not recognize the property, it assumes we’re referring to an element. Depending on the level, which is specified by the curly braces ({), the property becomes an XML element at that level. Attributes for an XML element can be specified like a method argument. For example, language (name: key) defines an attribute named name for an element whose name is language. The variable key’s value is substituted in the document as the value of the attribute name.

The output from the code in Listing 17 is the same as the content of the languages.xml file that we used as an input for the parsing example. In addition to Groovy, we could also fluently create XML documents using Scala, since that language treats XML as a first-class citizen and allows you to embed expressions in XML content.

Creating Expressive Code in Groovy

We saw the fluency of MarkupBuilder in the previous section. With Groovy metaprogramming, we can inject special methods into classes to create very fluent and expressive code. For example, we can facilitate the execution of code such as 2.days.ago quite easily. Let’s try exactly that example by creating a series of classes and methods, as shown in Listing 18.

import java.time.*

class DateUtil {
  int number

  DateUtil(aNumber) { number = aNumber }

  def getAgo() {

Integer.metaClass.getDays = { -> return new DateUtil(delegate) }

println 2.days.ago

Listing 18

The DateUtil class has a method named getAgo, which returns a LocalDateTime instance that is a number of days prior to now. The number property is initialized using the constructor. This is a pretty standard class that we’re used to writing. The core of the solution is in the code that follows this class.

In Groovy, we can inject methods into classes using a special meta Class property. In Listing 18, Integer.metaClass.getDays is a way to inject a getDays method into the java.lang.Integer class. We attach a closure (a lambda expression) as an implementation for this method. In this implementation, we create a new instance of DateUtil with the current Integer object—indicated by the delegate property—as the constructor argument.

As a final step, we’re ready to use the facility we’ve created. Instead of calling methods such as getDays and getAgo, we can use Groovy’s JavaBeans facility to use the corresponding property names, such as days and ago, as in the last line. Run this code to see it print out the date of the day that was two days before today.

Making Deep Recursion Possible Using Scala

Using a recursive approach, we can solve some problems by using solutions to their subproblems. Let’s first take a look at the small Scala example shown in Listing 19, and discuss the problems we will soon run into with this approach.

def factorial(number: BigInt) : BigInt = {
  if(number == 1)
    number * factorial(number - 1)

Listing 19

In Listing 19, the factorial() method uses recursion to compute the factorial of a given number. For small positive arguments, this code will yield the right result. However, for large values, it will run into StackOverflowError. The reason for this error is that the last operation performed in the recursive call is multiplication. This final operation forces the partial result to be held on the stack while the method waits for the result of the subsequent recursive call to be completed.

This problem can be avoided using a special technique called tail-call optimization. A tail-call is when the last call in a method is a call to itself. In other words, in Listing 19, we could rearrange the code so the last operation is not multiplication, but a call to the method factorial. This rearrangement would change the simple recursion into tail-recursive form.

Merely converting a recursion to a tail-call in any arbitrary language will not solve the problem, however. We need the language’s compiler or its library to support tail-call optimization to produce the desired effect. Thankfully, languages such as Scala and Clojure provide tail-call optimization through their compile support. In Scala, we can further enforce the tail-recursive form at compile time using a special annotation. Let’s convert the code to tail-recursive form, as shown in Listing 20.

def factorial(fact: BigInt, number: Int) : BigInt = {
  if(number == 1)
    factorial(fact * number, number - 1)

Listing 20

In this new version, the factorial method takes two parameters: the partial factorial result in the fact parameter and the number for which the factorial needs to be computed. Unlike the code in Listing 19, the last operation in Listing 20 is not multiplication. We multiply the partial result in fact with the current number and pass it as an argument to the factorial method. This recursive call is the last operation in the method when the recursion has to continue.

At compile time, the tailrec annotation will ensure that the method is in tail-recursive form. The compiler will optimize this code “under the hood” by converting the recursion into a mere iteration. Even for large input parameters, this code will not run into a stack overflow situation.

With this approach in mind, when working on applications where we want to employ recursive algorithms for large input sizes, we can benefit from tail-call optimization techniques.

Guaranteeing Resource Cleanup in Java

With the introduction of lambda expressions in Java, we can make use in Java of some good old patterns from the Smalltalk days. One such pattern is the Execute Around Method pattern, which is useful for wrapping a piece of code around some logic that we want to ensure is run. Let’s first discuss the problem and then look into why this pattern is a good option.

Suppose we have an object that uses extensive external resources and we want to clean up the object deterministically. Java SE 7 provides a special language feature called try-with-resources. This feature is also called Automatic Resource Management (ARM). Let’s look at an example of this feature, discuss some problems with it, and then look at an alternative solution.

Listing 21 shows a ResourceARM class that uses the ARM feature in Java SE 7.

public class ResourceARM implements AutoCloseable {
  public ResourceARM() { System.out.println(
                             "Resource created..."); }  public void op1() { System.out.println("op1"); }
  public void op2() { System.out.println("op2"); }
  public void close() { System.out.println(
   "cleanup logic goes here..."); }

Listing 21

To use the try-with-resources feature on a class, the class should implement the AutoCloseable interface. The ResourceARM class implements that interface and the required close method that would actively clean up the resources. Let’s use this class in an example.

In Listing 22, we placed the instance creation in the special form of try. This form removes quite a bit of noise in code; the finally block is not required because that part is synthesized by the compiler. In the synthesized finally block, the compiler automatically calls the close method on the instance we created in the try statement..

    try(ResourceARM resource = new ResourceARM()) {

Listing 22

With ARM, we have two benefits: the code is reduced—since we don’t have to write the finally block—and the resource cleanup is guaranteed at the end of the try block. This try-with-resources feature is useful when such deterministic cleanup is necessary.

The disadvantage of this feature, however, is that we have to use this form of the try block. ARM is a suggestive feature; it does not force us to do the right thing.

If we want to enforce a clear “use and clean up” boundary for code, we can use lambda expressions in Java SE 8 and employ the Execute Around Method pattern. Let’s create a code example for this approach (see Listing 23).

import java.util.function.Consumer;

public class Resource {
  private Resource() { System.out.println("Resource created..."); }
  public void op1() { System.out.println("op1"); }
  public void op2() { System.out.println("op2"); }
  private void close() { System.out.println("cleanup logic goes here..."); }

  public static void use(Consumer<Resource> block) {
    Resource resource = new Resource();
    try {
    } finally {

Listing 23

The Resource class in Listing 23 is much like the ResourceARM class in Listing 22, except it does not implement the AutoCloseable interface. The constructor and the close methods are declared private, which will prevent the user of the class from directly creating an instance or invoking the cleanup code. We provide a use method, which is marked static and takes as a parameter an instance of the new Java SE 8 Consumer interface. Within the use method, we create an instance of Resource and in the safe haven of the try and finally block, we pass the instance to the accept method of Consumer.

The use method is the implementation of the Execute Around Method pattern. It executes the proper creation and cleanup operation around whatever operation we intend to perform when accept is invoked.

With Java SE 8, we don’t have to create an instance of single, abstract method interfaces; we can use lambda expressions instead. Here is the code to use Resource:

    Resource.use(resource -> {

We invoke the use method of Resource and pass a lambda expression as an argument. In the lambda expression, we receive an instance of Resource that was passed to us from within the use method. We make use of this resource by calling methods such as op1() on it. When we return from the lambda expression, back in the use method, the cleanup operation takes place.

Learn More

 Java SE 8



Since we marked the constructor private, the use of the pattern is forced on programmers using the Resource class. Unlike the ARM feature, the Execute Around Method pattern is useful when the pre- and post-operations have to be guaranteed and the usage of the instance has to be rather narrow and enforced.


Simple tasks should be simple, and thanks to some highly capable languages available on the JVM, several routine tasks are now quite approachable. In this article, we looked at 10 different tasks and examined how to solve them using the capabilities of three different languages (Java SE 8, Scala, and Groovy).

Tasks that are arduous in one language might be quite easy to perform in another due to a special capability, a library, or a special construct, as we saw in this article. Each of these languages has capabilities and features that can help us with tasks far beyond the 10 tasks discussed in this article. By looking beyond the syntax—by exploring the libraries and key capabilities of the languages we adopt—we can leverage the languages to perform various routine tasks with greater ease.

Dr. Venkat Subramaniam (@venkat_s)is an award-winning author, founder of Agile Developer, Inc., and a professor at the University of Houston. He has trained and mentored thousands of software developers around the world and is a regular conference speaker. His latest book is Functional Programming in Java (Pragmatic Bookshelf, 2014).