Now, many Java developers like to use scripting languages in the Java platform, but it is sometimes not feasible to use dynamic languages compiled into Java bytecode. In some cases, it is quicker and more efficient to write a script part of a Java application directly or to invoke a particular Java object in a script.
That's why Javax.script. The Java scripting API, introduced from Java 6, fills the gap between a handy little scripting language and a robust Java ecosystem. By using the Java scripting API, you can quickly consolidate almost any scripting language in your Java code, which allows you to have more options to solve some of the smaller problems.
1. Use Jrunscript to execute JavaScript
Each new Java platform release will bring a new set of command-line tools in the JDK Bin directory. Java 6 is the same, where Jrunscript is a small complement to the Java Platform toolset.
Imagine a simple question of writing a command-line script for performance monitoring. This tool will use Jmap to run a Java process every 5 seconds to understand the health of the process. Typically, we use command-line shell scripts to do this, but the server applications here are deployed on some very different platforms, including Windows® and linux®. The system administrator will find it painful to write a shell script that runs on two platforms at the same time. The usual practice is to write a Windows batch file and a Unix®shell script, while ensuring that the two files are synchronized.
However, anyone who has read the pragmatic programmer knows that this is a serious violation of the DRY (Don T Repeat yourself) principle, and that there are many flaws and problems. What we really want is to write an OS-independent script that can run on all platforms.
Of course, the Java language is platform-independent, but this is not the case where you need to use the "system" language. What we need is a scripting language-like, JavaScript.
Listing 1 shows the simple shell script we need:
Listing 1. Periodic.js
while (true)
{
echo("Hello, world!");
}
Many Java developers already know JavaScript (or ecmascript;javascript is a ECMAScript language developed by Netscape) because they often deal with Web browsers. The question is, how will the system administrator run this script?
The solution, of course, is the Jrunscript utility that the JDK brings, as shown in Listing 2:
Listing 2. Jrunscript
C:\developerWorks\5things-scripting\code\jssrc>jrunscript periodic.js
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
...
Note that you can also use the For loop to loop through the script at a specified number of times before exiting. Basically, Jrunscript allows you to perform all the actions of JavaScript. The only difference is that its runtime is not a browser, so there is no DOM in the run. Therefore, the topmost functions and objects are slightly different.
Because Java 6 takes the Rhino ECMAScript engine as part of the JDK, Jrunscript can perform any ECMAScript code passed to it, whether it's a file (as shown here) or in a more interactive REPL ("Read-evaluat E-print-loop ") shell environment. The REPL shell can be accessed by running Jrunscript.
2. Accessing Java objects from scripts
It's nice to be able to write javascript/ecmascript code, but we don't want to be forced to recompile all the code we use in the Java language--that's against our original intent. Fortunately, all the code that uses the Java Scripting API engine is fully accessible to the entire Java ecosystem, because all the code is still Java byte code. So, back to our previous question, we can use the traditional runtime.exec () call on the Java platform to start the process, as shown in Listing 3:
Listing 3. Runtime.exec () Start Jmap
var p = java.lang.Runtime.getRuntime().exec("jmap", [ "-histo", arguments[0] ])
p.waitFor()
An array arguments is a ECMAScript standard built-in reference to a parameter passed to this function. In the top-level scripting environment, it is an array of arguments (command-line arguments) that are passed to the script itself. So, in Listing 3, this script expects to receive a parameter that contains the VMID of the Java process to map.
In addition, we can use the Jmap itself as a Java class and call its main () method directly, as shown in Listing 4. With this approach, we do not need to "transfer" the In/out/err stream of the Process object.
Listing 4. Jmap.main ()
var args = [ "-histo", arguments[0] ]
Packages.sun.tools.jmap.JMap.main(args)
The Packages syntax is a Rhino ECMAScript identifier that points to a Java package created within the Rhino that is located outside the core Java.* package.