Visit Java's Relatives: Jython and Groovy

By Jeff Friesen

Date: May 4, 2007

Return to the article


Out of the many JRE-hosted languages in existence, this article focuses on the popular Jython and Groovy languages. Jython is a Java version of the Python language, whereas Groovy is based on Java. In addition to introducing Jython and Groovy, programmer Jeff Friesen shows you how to download and install necessary software, and takes you on a brief tour of each language.

The Java Runtime Environment (JRE) can host languages other than Java. This flexibility is perfect for non-Java developers who want to work within the contexts of their own languages, while reaping JRE benefits (such as a cross-platform virtual machine with security features). And this flexibility is perfect for Java developers who want to explore the potential of other languages, while staying with the familiar JRE. To illustrate the JRE's language flexibility, this article introduces the Jython and Groovy JRE languages.

Jython

Jython is a Java implementation of the Python language. Written entirely in Java, Jython is available to all Java platforms. This interpreted, interactive, and object-oriented language combines Java’s robustness with Python’s flexibility and ease of use, which encourages productivity and makes this language perfect for rapid application development.

Download and Install Jython

Before we tour Jython, let’s download and install the current production release: Jython 2.1. This version was released on December 31, 2001, and corresponds to Python 2.1. Begin by pointing your Web browser to the official Jython site and select the Download link on the main page. On the resulting Downloads page, select the jython-2.1 link to start the download.

After downloading the 2.65MB jython-21.class installer file, follow these steps:

  1. Open a command window and move to the directory containing this file.
  2. Type java jython-21 and press Enter to begin installation.
  3. If you are running Windows XP, you will probably notice an error message and a dialog box. Respond by selecting the Windows list item and clicking the OK button.
  4. The installer now presents an Install dialog box—see Figure 1—where you can select an installation language (English or German), an installation type (All: everything, Standard: everything but sources, and Minimum: only the core files), and individual checkboxes for choosing a combination of core files, library modules, demos and examples, and sources.
  5. Click Next to continue.
    Figure 1

    Figure 1 Verify the Jython version and determine how much of the Jython distribution gets installed.

  6. The dialog box now identifies the operating system and Java version. It also presents a checkbox that lets you decide whether to launch Jython with a console window (unchecked, the default—for Windows XP, java.exe is used to launch Jython) or without a console window (checked—for Windows XP, javaw.exe is used to launch Jython). Leave the checkbox unchecked and click the Next button.
  7. The dialog box next presents a license agreement. Read this agreement and click the Accept button.
  8. The dialog box next asks you to choose the location in which to install Jython. For my Windows XP platform, I chose c:\jython.
  9. After choosing Jython’s home directory, click the Next button.
  10. The dialog box tells you that it is ready to copy files. Press the green Go! button and the file-copying begins.
  11. After the files have been copied, a readme file is presented, which identifies some important changes in the 2.1 version. Once you finish reading this file, click the Exit button to close the installer.

Because I installed Jython on a Windows platform, my Jython home directory contains jython.bat. This batch file launches the Jython interpreter via a java command (or javaw command, if you chose to launch Jython without a console window). Before you can invoke this batch file (or UNIX equivalent) from any directory, add your Jython home directory to your path environment variable.

A Brief Jython Tour

The simplest way to launch the interpreter is to type jython by itself on the command line. This command launches Jython in interactive mode, with the following standard greeting message:

Jython 2.1 on java1.5.0 (JIT: null)
Type "copyright", "credits" or "license" for more information.
>>>

Jython supports the basic integer, floating-point, and string data types. Expressions can be built from these basic types and evaluated in a simple manner:

>>> 4*3*2*1 # Calculate 4 factorial.
24
>>> 3.14159*45/180 # Convert 45 degrees to radians equivalent.
0.7853975
>>> "Hello, "+"World" # Concatenate to strings.
’Hello, World’

Except for #, which introduces a comment (ignored by the interpreter), this Jython expression code looks much the same as Java expression code. Here are some differences:

>>> pi=3.14159 # Variable types are inferred from expressions.
>>> pi
3.14159
>>> i=j=k=1 # Multiple variables can be assigned the same value.
>>> i
1
>>> j
1
>>> k
1
>>> cn1=30+2j # Jython supports complex numbers.
>>> cn1.real # You can access the real part...
30.0
>>> cn1.imag # ...and the imaginary part.
2.0
>>> cn2=15-6j
>>> cn1+cn2 # You can also perform standard complex arithmetic.
(45-4j)
>>> str1="String 1" # Strings can be enclosed in double quotes...
>>> str1
’String 1’
>>> str2=’String 2’ # ...or in single quotes.
>>> str2
’String 2’
>>> str1[0] # Single characters can be extracted using an index.
’S’
>>> str1[0:2] # A substring can be returned via two indexes separated by a colon.
’St’
>>> str2[2:] # With no second index, substring continues to end of string.
’ring 2’
>>> str2[:3] # With no first index, substring begins at start of string.
’Str’

Jython’s equivalent to Java arrays is its flexible list type. A list is expressed as a comma-delimited sequence of values placed between square brackets:

>>> languages=[’Jython’,"JRuby",’Groovy’] # Create a list.
>>> languages
[’Jython’, ’JRuby’, ’Groovy’]
>>> languages[0]="Java" # Replace the first list item.
>>> languages
[’Java’, ’JRuby’, "Groovy’]
>>> languages=languages+[’Jython’] # Append a list item.
>>> languages
[’Java’, ’JRuby’, ’Groovy’, ’Jython’]
>>> languages[0:1]=[] # Remove a list item.
>>> languages
[’JRuby’, ’Groovy’, ’Jython’]
>>> len(languages) # The len() function returns a list’s length.
3
>>> languages[1]=[1,"Groovy",3] # Lists can contain different-typed values.
>>> languages # Furthermore, lists can contain lists.
[’JRuby’, [1, ’Groovy’, 3], ’Jython’]

Jython supports a variety of statements, including the while and for loop statements, the break and continue loop-control statements, and the if decision statement:

>>> fact=n=1
>>> while n < 11:
...   print n, fact
...   n=n+1
...   fact=fact*n
...
1 1
2 2
3 6
4 24
5 120
6 720
7 5040
8 40320
9 362880
10 3628800
>>> for age in [50,57,68]:
...   if age < 55:
...       print "Not eligible for early retirement"
...   elif age < 65:
...       print "Not eligible for traditional retirement"
...   else:
...       print "Retired"
...
Not eligible for early retirement
Not eligible for traditional retirement
Retired
>>> for i in range(0,10):
...   print "i =", i
...
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9

You’ll notice many similarities between these Jython statements and their Java counterparts. You’ll also notice many differences. These differences include:

The for statement is similar to Java 5.0’s enhanced for statement. Each iteration retrieves the next list item (the range() function returns a list of integers) and assigns it to the loop variable.

In addition to using Jython’s built-in functions (such as len() and range()), you can define (via Jython’s def keyword) and use your own functions:

>>> def fact(n):
...   i=factorial=1
...   while i <= n:
...       factorial=factorial*i
...       i=i+1
...   return factorial
...
>>> for i in range(0,11):
...   print "i =", i, ": fact =", fact(i)
...
i = 0 : fact = 1
i = 1 : fact = 1
i = 2 : fact = 2
i = 3 : fact = 6
i = 4 : fact = 24
i = 5 : fact = 120
i = 6 : fact = 720
i = 7 : fact = 5040
i = 8 : fact = 40320
i = 9 : fact = 362880
i = 10 : fact = 3628800

Functions can be defined inside classes. Functions defined with keyword self (Jython’s equivalent of Java’s this keyword) as the initial parameter are equivalent to Java’s instance methods:

>>> class Employee:
...   name=""
...   __age=0
...   def __init__(self,name,age):
...       self.name=name
...       self.__age=age
...   def getAge(self):
...       return self.__age
...
>>> john=Employee("John Doe",37) # Construct Employee object.
>>> john.name
’John Doe’
>>> john.__age
Traceback (innermost last):
 File "<console>", line 1, in ?
AttributeError: instance of ’Employee’ has no attribute ’age’
>>> john.getAge()
37

The Employee class defines two variables (name and __age) and two method functions (__init__ and getAge()). These definitions illustrate two points:

To close this tour, let’s look at importing Java classes into Jython. This task is accomplished with the from package import class directive:

>>> from java.util import StringTokenizer
>>> s = StringTokenizer("Jython can easily access Java classes")
>>> s.nextToken()
’Jython’
>>> s.nextToken()
’can’
>>> s.nextToken()
’easily’
>>> s.nextToken()
’access’
>>> s.nextToken()
’Java’
>>> s.nextToken()
’classes’
>>> s.nextToken() # Guess what happens?

I excerpted the earlier Jython code fragments from a jython.py script (part of this article’s code)—.py is the standard Jython file extension. You can run this script by passing it as an argument to jython.bat (or the UNIX equivalent). Example: jython jython.py.

Groovy

Like Jython, Groovy is a scripting language for the Java platform. Unlike Jython, which shares the syntax of Python, Groovy’s syntax is close to Java (and Groovy reuses standard Java libraries). As a result, developers do not need to spend lots of time learning Groovy. I like to think of Groovy as Java lite—a less-restricted Java.

Download and Install Groovy

On January 2, 2007, Groovy 1.0 was officially released. This is the version we will download and install. Begin by pointing your Web browser to the official Groovy site and click the Download link. On the resulting web page, click the version 1.0 binary release zip or tar/gz link (as appropriate). Unzip the archive’s contents to a suitable home directory (I chose c:\groovy).

Add the Groovy home directory’s bin directory to the path environment variable to complete the installation. This step will let you run Groovy scripts (via the groovy shell script or the groovy.bat batch file, or via a native launcher—to learn how to build a native launcher, check out this page) from any directory.

A Brief Groovy Tour

Groovy is an interpreted language. To interpret a Groovy program (or script), specify groovy followed by the script’s filename at the command line. Listing 1 presents a simple script—notice the standard .groovy file extension.

Listing 1 groovy.groovy

// groovy.groovy

// Groovy supports Jython-style lists. Because of groovy’s dynamic typing, you
// do not need to specify a variable’s type. You also don’t need to specify
// semicolon terminators.

months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
     "Oct", "Nov", "Dec"]

// You can use a Jython-style for loop to output the list’s items.

for (month in months)
  println month

// You can use an inclusive range if you want to access list items by index.

for (monthIndex in 0..11)
  println months[monthIndex]

// Classes can include properties.

class Salesman
{
  String name // name is a property of Salesman
}

class Author
{
  String name // name is a property of Author
}

// Object creation is similar to Java.

s = new Salesman()

// Properties can be accessed directly.

s.name = "John Doe"

a = new Author()

// Properties can be accessed via getter/setter methods -- with or without
// surrounding parentheses.

a.setName "Jane Smith"

people = [s, a]
for (i in people)
{
  println i.name
  i.setName (i.name.reverse()) // name must be of String type
  outputPerson (i)
}

// Functions can be defined globally outside of classes. For this function,
// any object with a name property can be passed as an argument.

def outputPerson(person)
{            
  println person.getName ()
}

// The following class demonstrates the usefulness of closures.

class Formatter
{
  Object format

  def doFormat (p, Object[] args)
  {
   format.call (p, args) // Invoke closure with initial pattern and a...
              // ...variable number of arguments.
  }
}

// Imports can be placed where needed.

import java.text.*

// Create a currency formatter closure.

curFormatter =
{
  value, Object[] args ->
   println NumberFormat.getCurrencyInstance ().format (value)
}

// Create a message formatter closure.

msgFormatter =
{
  pattern, Object[] args ->
   println MessageFormat.format (pattern, args)
}

// Create a Formatter with a message formatter closure.

f = new Formatter (format: msgFormatter)

// Format a generic message.

f.doFormat ("The date is {0, date}; the time is {0, time}",
      new java.util.Date())

// Create a Formatter with a closure for strictly formatting currency values.

f = new Formatter (format: curFormatter)

// Format a currency value.

f.doFormat (137.9256)

Listing 1 shows that Groovy is less restrictive than Java: semicolons are not used to terminate statements, types are not specified in non-property variable declarations, parentheses are optional in method calls, and imports are not restricted to the beginning of the source code.

Listing 1 also reveals Groovy’s list data structure, for loop/numeric range (0..11 indicates an inclusive range from 0 through 11; in contrast, 0...11 indicates an exclusive range from 0 through 10), property-access, "define function outside of class", and closure features.

To run this script from the command line, specify groovy groovy.groovy. In response, you will see output that (except for the date and time) is identical to the following output:

Jan
Feb
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec
Jan
Feb
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec
John Doe
eoD nhoJ
Jane Smith
htimS enaJ
The date is Mar 5, 2007; the time is 6:09:43 PM
$137.93

Perhaps the best way to gauge Groovy’s usefulness as a rapid prototyping language is to compare Java source code with its Groovy counterpart. Listing 2 presents a Swing-based text-file viewer’s Java source code.

Listing 2 Viewer.java

// Viewer.java

import java.io.*;
import java.util.ArrayList;
import javax.swing.*;

public class Viewer
{
  public static void main (String [] args)
  {
   if (args.length != 1)
   {
     System.out.println ("usage: java Viewer filename");
     return;
   }

   ArrayList<String> lines = new ArrayList<String> ();

   BufferedReader br = null;
   try
   {
     FileReader fr = new FileReader (args [0]);
     br = new BufferedReader (fr);

     String line;
     while ((line = br.readLine ()) != null)
       lines.add (line);
   }
   catch (IOException e)
   {
     System.out.println ("unable to read " + args [0]);
     return;
   }
   finally
   {
     try
     {
       if (br != null)
         br.close ();
     }
     catch (IOException e)
     {
     }
   }

   JList list = new JList (lines.toArray ());

   JFrame frame = new JFrame ("Viewer: " + args [0]);
   frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
   frame.add (new JScrollPane (list));
   frame.setSize (300, 300);
   frame.setVisible (true);
  }
  }

The Viewer application requires a single command-line argument, which identifies a text file whose content is to be displayed. Figure 2 shows the result of invoking java Viewer Viewer.java.

Figure 2

Figure 2 A text file’s content is displayed in a scrollable list.

Listing 3 presents the equivalent Viewer.groovy Groovy script—you can view the contents of this script by invoking groovy Viewer.groovy Viewer.groovy.

Listing 3 Viewer.groovy

// Viewer.groovy

import java.io.File
import java.util.ArrayList
import javax.swing.*

if (args.length != 1)
{
  println "usage: groovy Viewer.groovy filename"
  return
}

lines = new ArrayList<String> ()

new File (args [0]).eachLine
{
  line -> lines.add line
}

list = new JList (lines.toArray ())

frame = new JFrame ("Viewer: " + args [0])
frame.setDefaultCloseOperation JFrame.EXIT_ON_CLOSE
frame.add new JScrollPane (list)
frame.setSize 300, 300
frame.setVisible true

Listing 3 is much shorter than the previous listing. This brevity is due to what you have previously learned about Groovy, and these additional items:

Java’s try block/catch exception handler/finally cleanup clause are not required. Groovy automatically closes open files when eachLine() finishes iterating, regardless of whether an exception is thrown.

Finally, although Viewer.groovy does not present an enclosing main() function that identifies an array/list of command-line arguments, you can still access these arguments via Groovy’s predefined args array/list.

Conclusion

Because the need for brevity limited my coverage of Jython and Groovy, I recommend that you examine the previously specified resources to learn more about these languages. You might also want to point your browser to Languages for the Java VM, and visit Java’s other relatives.