Summary
JSR 223, Scripting for the Java Platform, defines a way to integrate Java and scripting languages. The first implementation this JSR is already a part of JDK 1.6 "Mustang" beta. A recent article looks at some of the key JSR 223 features, including how to make a Java program scriptable, and how to invoke scripts from a Java application.
Advertisement
While some prefer to debate the relative merits of scripting languages vis-a-vis Java's generally more structured ways, there is no reason why Java developers cannot take advantage of the best scripting language features while also retaining all of Java's benefits, including Java's rich APIs.
JSR 223, Scripting for the Java Platform, defines both Web scripting and client-side scripting. The former deals with cases when a script is part of a Web application; many PHP and JavaScript snippets would work in that context.
Client-side scripting details how a developer can integrate a scripting-language into a Java application that is not part of a Web app. For instance, instead of coding in Java, a developer can use a scripting language to tie together various Java components in support of some application functionality. The advantage is that the script is presumably easier to change than a corresponding Java program would be, and changes to a script typically require no recompilation.
The benefit of scripting Java applications is not limited to developers. End-users have a long history of automating tedious tasks in office productivity programs with macros written in scripting languages easy enough for users to master. JSR 223 will make such user-scriptable applications also possible.
JSR 223 is slated to become available in JDK 1.6, and the downloadable Mustang beta already contains a sufficient functionality to try some of the features. Thomas Künneth has done just that in a recent java.net article, Scripting for the Java Platform, providing an overview of client-side scripting in the javax.script package. He details how a scripting engine is integrated with the JVM using the JAR service provider mechanism:
From a client application's point of view, the entry class to scripting is ScriptEngineManager, which implements a discovery and instantiation mechanism for script engines. [...] Applications utilize this mechanism by instantiating ScriptEngineManager. They can then obtain instances of specific script engines; for example, by invoking getEngineByExtension(), getEngineByMimeType(), or getEngineByName(). Alternatively, you can call getEngineFactories() and examine its results, which are instances of ScriptEngineFactory.
The current Mustang beta ships with the Rhino JavaScript engine, and Thomas shows examples of invoking JavaScript from within a Java program:
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine e = sem.getEngineByName("ECMAScript");
ScriptEngineFactory f = e.getFactory();
String [] statements = {
"var a = 2;",
"var b = 3;",
"var c = a + b;",
"print(\"a + b = \" + c);"
};
String program = f.getProgram(statements);
try {
e.eval(program);
} catch (ScriptException ex) {
ex.printStackTrace();
}
It's also easy to open external files containing a script, and look up the appropriate scripting engine based on the script file's extension.
Thomas also explains that a JSR 223-compliant script engine can expose a front- and back-end interface. The front end is responsible for parsing a script to an intermediate representation that the back-end then executes. The engine might parse a script once, and thereafter just invoke the intermediate representation. The front and back ends are defined by the Compilable and Invocable interfaces.
Finally, the article explains how scripts interact with a Java application via Bindings and ScriptContext:
A scope represents a set of key-value pairs. It is stored in objects implementing javax.script.Bindings. It maps the names of script variables to their values. [...] Reading the value of a key in the engine scope returns the value of the corresponding script variable. [...] Sets of scopes are passed to script engines using instances of ScriptContext.
Whenever a script engine executes a script, it uses a ScriptContext, which may have been passed to eval(). If this is not the case, a default script context, which is maintained by the script engine, is used. The default script context can be changed at any time.
Besides scopes, ScriptContext offers methods returning Readers and Writers. Script engines use them for input and output purposes.
What do you think of JSR 223's approach to integrating scripting languages and Java? Do you envision scripting being used to quickly tie together Java components in support of more complex application logic?
Finally an easy way for someone to create a Grease Monkey feature for Eclipse.
While Eclipse is extendable, and has a great plugin architecture, enabling a scripting engine to be accessed from the IDE - and those scripts being able to access IDE componentry would enable many devlopment teams to solve domain specific problems more easily.
1> Refactorings could be written as simple scripts that leverage the Eclipse capabilities to find methods and types.
2> Ad-hoc transformations of data in XML or other formats could be done - and tweaked as needed during volitile stages of development where formats haven't solidified.
3> Automation of code generation - classes and methods - would be facilitated.
These features can already be integrated into Eclipse via the plugin architecture, but a scripting engine interface would make it even more accessible.
> These features can already be integrated into Eclipse via > the plugin architecture, but a scripting engine interface > would make it even more accessible.
Everything you want is already possible right now with two simple Plugins:
- EclipseShell: an interactive shell that allows you to use a scripting language; it supports Beanshell, JRuby and Javascript (Rhino). It also makes it easy to save your sessions, has AutoComplete for your variables and methods, etc etc. See here: http://eclipse-shell.sourceforge.net/ or here for screencasts showing it's capabilities: http://eclipse-shell.sourceforge.net/screencasts.html It's very easy (and fun) to play around with Eclipse plugins and the APIs they expose. (Disclaimer: I'm the maintainer of this plugin).
- Ward Cunningham & Co have built the EclipseMonkey plugins which also introduced the notion of "DOMs" (Domain object models), a fancy name for "simplified versions of Eclipse APIs that make them easy to use from a scripting language". EclipseMonkey is Javascript(RHino) only, but has many nice features eg to facilitate distribution of the EclipseMonkey scripts. See the website: http://www.eclipse.org/dash/ BTW: EclipseMonkey DOMs can easily be accessed from all languages that run with EclipseShell.