X
Tech

Integrating scripts into Java applications

A lot of Java applications today can be extended viz. adding new features to the application by writing "plug-ins" in Java. Lee Chuk-Munn shows how.
Written by Lee Chuk-Munn, Contributor
A lot of Java applications today can be extended, viz. adding new features to the application by writing "plug-ins" in Java. One such example of this is the NetBeans plug-in framework. We can invoke scripts from within Java applications which will allow us to write these plug-ins with scripting languages.

In a previous article, we saw how easy it is to use scripting languages like JavaScript to create and manipulate Java objects. In this article we will look at invoking a script from within a Java program. The scripting classes are located in javax.script package.

The classes provide the following functionalities:

  1. Executing a script
  2. Binding - exposing Java objects into the scripting environment
  3. Compilation - compile a script. This is an optional feature; not all script engines support this
  4. Invocation - calling a function in the script. This is again an optional feature.

Here are the steps to integrate scripting into Java applications:

  • Create an instance of the script engine class; do not forget to import the javax.script package
ScriptEngineManager manager = new ScriptEngineManager();

  • Use the script engine to look up the scripting engine of a script language; JavaScript is the default language supported in Mustang. So we will use that. In a future article, we will look at how you can add your favorite script language into Mustang.
ScriptEngine engine = manager.getEngineByName("js");

  • You can expose Java objects from your Java application into any script. This is known as binding. To bind a Java object, you need to give the Java object a name which will be used as a reference inside the script. In the example below, we will bind a JFrame instance to the name "FRAME".

//Create any Java object
JFrame frame = new JFrame("My frame");
//Add some components into JFrame - not shown
...
//Create a binding object
SimpleBindings bindings = new SimpleBindings();
bindings.put("FRAME", frame);
engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE);

The ENGINE_SCOPE specifies that the bindings will be visible to all scripts executed by the engine instance.

  • Now we load and execute the desired JavaScript
FileReader script = new FileReader("some_java_script.js");
engine.eval(script);

You can eval() multiple scripts with a single instance of engine. The effect of this is that any method or variable defined by  preceeding scripts will be available to later scripts. This is typically used to initialize the script engine environment viz. pre-populate the engine with utility functions and variables that other scripts rely on.

  • some_java_script.js might look something like this
//Define an add function
function add(a, b) {
   return (a + b);
}

//Make the JFrame visible
FRAME.setVisible(true);

  • We can also selectively invoke a particular function in an evaluated script. For this you need to specify the name of the script and the parameters of the script. We use to invoke() method in Invocable to do this. However, this feature is not a mandatory feature, so we have to check if  the engine supports it.
//Check if the engine implements the Invocable interface
if (!(engine instanceof Invocable)) {
   System.err.println("The script engine does not support Invocable");
   return;
}
//Cast the engine to the Invocable interface
Invocable inv = (Invocable)engine;
try {
   System.out.println("result = " + inv.invoke("add", oper1, oper2));
} catch (ScriptException e) {
   System.err.println(e.getClass().getName() + ":" + e.getMessage());
} catch (NoSuchMethodException e) {
   System.err.println(
e.getClass().getName() + ":" + e.getMessage());
}

Lee Chuk-Munn has been programming in the Java language since 1996, when he first joined Sun Microsystems in Hong Kong. He currently works as a senior developer consultant and technology evangelist for Technology Outreach at Sun in Singapore. Chuk's focus is in Java APIs, Java EE, Java SE, and Java ME. Chuk graduated in 1987 from the Royal Melbourne Institute of Technology in Melbourne, Australia, where his favorite subject was compiler theory.

Editorial standards