Thursday, June 2, 2011

jrunscript and Groovy

There are numerous tools provided with Oracle's HotSpot JDK that Java developers use everyday when they use the Java compiler ('javac'), the Java launcher ('java'), or the Java Archive Tool ('jar'). Because of its frequent use, the JDK installation's ($JAVA_HOME or %JAVA_HOME%) bin directory is typically on the Java developer's PATH. The implication of this is that many more useful tools that come with Oracle's JDK distribution are also available on the path. I have blogged about some of these tools including jvisualvm, jconsole, jps, serialver, rmiregistry, xjc, schemagen, jinfo, and jhat and jmap. In this post I cover a tool in this directory that I've not covered before: jrunscript.

The jrunscript tool is a "command line script shell" that is described on its JDK 7 tools page as "a command line script shell" that "supports both an interactive (read-eval-print) mode and a batch (-f option) mode of script execution." The page adds further description:
This is a scripting language independent shell. By default, JavaScript is the language used, but the -l option can be used to specify a different language. Through Java to scripting language communication, jrunscript supports "exploratory programming" style.

As is the case with many tools in the JDK bin directory, this tool comes with this caveat: "NOTE: This tool is experimental and may not be available in future versions of the JDK." That being stated, it has been available in both Java SE 6 and so far in Java SE 7 JDK distributions from Sun/Oracle.

The usage for jrunscript can be seen by simply typing jrunscript -help at the command prompt. The next screen snapshot demonstrates this after first showing the current version of Java and Groovy involved. Although these are fairly current versions of both languages, slightly older versions of each (Java SE 6 for example) can be used for most of my examples.


The usage of jrunscript is fairly straightforward as its usage indicates. Using the -q option instructs jrunscript to report which scripting engines are available. The default available script engine is Rhino JavaScript as is shown in the next screen snapshot.


JavaScript is not the only supported scripting language for jrunscript. In the remainder of this post, I will demonstrate use of Groovy as the scripting language used in conjunction with jrunscript.

To run a scripting language other than the out-of-the-box-provided Rhino with jrunscript, a JSR 223-compliant script engine JAR is typically needed as described in JSR-223 script engine for the Java language. Fortunately, in the case of Groovy 1.6 or later, this JSR 223 engine is built into the language.

When I place the appropriate Groovy JAR files (groovy-1.8.0.jar and asm-3.2.jar) on the classpath provided to jrunscript and pass it the -q option ("List all scripting engines available and exit") to determine which languages are supported, it now tells me that Groovy is supported in addition to the default Rhino JavaScript. This can be seen in the next screen snapshot.


Even with the applicable Groovy JAR files on the classpath, the default scripting language that jrunscript uses is JavaScript unless a different language is specified with the -l option. The next screen snapshot demonstrates this is the case.


I've gotten this far with only needing to specify two Groovy JARs on the classpath when running jrunscript. However, if I do too many operations, other JARs will be needed or else I'll see a NoClassDefFoundError.

The next screen snapshot shows invocation of jrunscript with three Groovy JARs. More than showing the use of the JARs, the output also demonstrates using jrunscript interactively to get calculate a sum, to get the current date/time via the Date class, and to get the current date/time via Calendar.getInstance(). This demonstrates the ability to interactively perform simple Groovy statements and thus do some "exploratory learning."


The above output was generated from using jrunscript with Groovy interactively. Groovy code can also be written to a file and executed via jrunscript. For example, the file groovyScript.groovy can be created as shown next.

groovyScript.groovy
def sum = 12 + 13 + 14
def date = new Date()
def calendar = Calendar.getInstance()
println "Sum:      ${sum}"
println "Date:     ${date}"
println "Calendar: ${calendar}"

The above file can be executed via jrunscript as shown in the next screen snapshot. Note that the -l option is specified to instruct jrunscript that the code in the file is Groovy.


The advantage of running jrunscript against a script file with Groovy code is that variables defined earlier in the script are still available in later statements.

The jrunscript tool also supports a -e option that allows script code to be passed inline to the tool. The next screen snapshot demonstrates doing just this with the -l option again specifying Groovy as the language and the -e option passing in the script to run. The partial output from running this is included in the screen snapshot.


I have demonstrated in this blog post how to use jrunscript to run Groovy code. In particular, I've shown using Groovy interactively via jrunscript, passing a Groovy script in a single string to jrunscript, and executing jrunscript against a file with Groovy script code. These options all work, but the truth is that they're really more valuable for a non-JVM scripting language like JavaScript than they are for a JVM-based scripting language like Groovy. The difference is that Groovy is already very Java-friendly and has virtually seamless integration with Java. Indeed, there are easier and arguably better ways to run Groovy code from the command line than using jrunscript. I cover these briefly now.

If I want to run Groovy code in a file, the obvious choice is to simply use the 'groovy' launcher and run the script. I have demonstrated this in many Groovy posts on this blog. This same groovy launcher also supports a -e option just like jrunscript does. The advantage of the Groovy launcher approach over use of jrunscript in both cases is a much simpler explicit classpath specification. More information on Groovy from the command line can be found in the Groovy User Guide's Groovy CLI page.

The native groovy launcher more than adequately covers jrunscript's ability to allow Groovy code in a file to be executed or Groovy code in a String to be executed in a single command. To match (and exceed) jrunscript's interactive functionality when using Groovy, the obvious choice is Groovy shell. I have covered Groovy Shell in a previous blog post. It is simple to use and is shown in the next screen snapshot.


Conclusion

For non-JVM scripting languages that provide a JSR 223 compliant scripting engine, jrunscript can be a valuable tool. In the case of Groovy, I cannot think of a good reason to pick jrunscript with Groovy over simply using the Groovy native launcher (groovy) and Groovy Shell (groovysh) directly. This might be the reason that there are not many online resources talking about using Groovy with jrunscript. For more details on use of jrunscript with scripting languages other than Groovy, see Use jrunscript to execute JavaScript scripts and Using jrunscript to create a build script.

No comments: