Articles
Dynamic Scripting Languages
|
|
| By Carol Zhang, June 2008 |
|
In recent years, Google search trends show that searches for the word "Java" are declining slightly, and searches for scripting language names, like JavaScript, PHP, Ruby, Python, and Rails, are increasing. Some people are talking about the dismissal of Java and its replacement with these scripting languages. Though we can not predict the future of the Java programming language in this article, we have solid reason to believe that Java is still a mainstream programming language in the world, and it will exist for a long time. There is a very large and stable ecosystem around Java, which includes large vendor support, killer applications, wide deployment, development and deployment tools, lots of experienced programmers, mature communities, comprehensive training, and low entry costs. This is the huge momentum of a successful language.
The rise of the scripting languages is driven by agile development requirements in the Web 2.0 era. Scripting languages enable rapid and easy development with features:
However, scripting languages fall short if they are used to build large-scale or mission-critical applications, due to potential scalability and performance issues. Also, most scripting languages are not designed for team collaboration.
Java and scripting languages are not mutually exclusive. On the contrary, they are complementary and can play together in many scenarios.
Combining scripting languages with the Java platform provides developers an opportunity to leverage the abilities of both environments. You can continue to use scripting languages for all the reasons you already have, and you can use the powerful Java class library to extend the abilities of those languages. If you are a Java language programmer, you now have the ability to ship applications that your customers can significantly and dynamically customize. The synergy between the Java platform and scripting languages produces an environment in which developers and end users can collaborate to create more useful, dynamic applications.
Let's take Project Phobos as an example, to see what magic can be produced with the integration of Java and scripting languages. The goal of Phobos is to build a lightweight web application framework that runs on the Java platform, but allows you to develop your entire application using a scripting language, such as JavaScript. As a result, you can take advantage of the many benefits that scripting languages offer, but still leverage the power of the Java platform.
If you intend to use scripting to implement a portion of your Java applications, you will need to decide when to use which technologies, considering each language has its own strengths and weaknesses. Though normally it should be analyzed case by case:
Consider using scripting:
Consider using Java:
A number of approaches also allow Java applications to interoperate with code written in other languages. For example:
Basically, the interaction will be of one of two types. Either the Java application and the separated processes, which communicate by using inter-process techniques, like Web Services, or the Java application and the other reside in the same process, as with JNI. The technology used depends on the system requirement and the existing architecture.
It is a similar story when Java interacts with scripting languages. The Web Services approaches can be chosen for the loosely-coupled applications written in script, and if it is both cumbersome and inefficient to manipulate scripting files through another process, then the in-process integration method between Java and scripting language may be considered. Since the inter-process integration technologies are well-known and mature, then in this article, we will mainly discuss how Java and scripting language interoperate within one process.
Several common questions are asked when people are writing programs to interface Java applications with code written in other scripting languages:
JSR-223, Scripting for the Java Platform, defines a standard, portable, scripting language-independent way to allow Java programs to interact with scripting languages. Here's a brief introduction to how Java Scripting Framework solves the above questions.
|
Figure 1. Diagram: the internal of the Scripting Engine
|
The core of the Java Scripting Framework is the Scripting Engine, as shown in the above diagram. It is a pluggable software component that executes programs written in some scripting language. The execution is generally performed by an interpreter. You can implement the engine in Java or make a Java wrapper around a native language interpreter. Conceptually, an interpreter consists of two parts: a front-end which parses the source code and produces an internal representation of the program known as intermediate code, and a back-end which uses the intermediate code to execute the program.
The specification refers to a Script Engine Discovery Mechanism to automatically discover the Scripting Engines at runtime and query for attributes that an application can use to determine their capabilities and usability. It also means that you can add new Script Engines to your runtime environment as common JAR extensions.
Scripting Engines are allowed to store Java objects and class references and use them in scripts by the mechanism of Java Language Bindings. Bindings are created by a built-in scripting function to allow scripts to access public methods and fields of objects, and public static methods and fields of classes. Typically, the binding keeps the key/value mappings:
The data types represented by script variables vary depending on the scripting language and the script engine implementation. In each invocation from Java code to script code, a data type conversion would be executed when passing the Java object as arguments and returning the value from the function call. You should check with the script-specific document about the data type conversion.
Now that we've covered the essentials of the integration and the standardized approaches in the Java specification, we will talk more about the methods of two-way integration: one is scripting within the Java application, the other is scripting the Java object. Let's look at them in detail.
The Java Scripting Framework provides a set of scripting APIs, which allow Java Scripting Engines to be used in Java applications. The API is intended for use by application programmers who wish to execute programs written in scripting languages, in their Java applications. Let's go through a code sample to see how this can be achieved.
The simplest way to use the scripting API is as follows:
import javax.script.*;
public class EvalScript {
public static void main(String[] args) throws Exception {
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName("JavaScript");
// create a Java object
String name = "Tom";
// create the binding
engine.put("greetingname", name);
// evaluate JavaScript code from String
engine.eval("println('Hello, ' + greetingname)");
engine.eval("println('The name length is ' + greetingname.length)");
}
}
|
The output is:
Hello, Tom The name length is 3 |
Let's go through the code sample:
You can use the Scripting API to achieve the following tasks:
You may refer to the Java Scripting Programmer's Guide for the programming details about how to implement the above functions.
Beside Java Scripting Framework as a standardization effort in this area, the Jakarta Bean Scripting Framework (BSF) is also worthy of mentioning. Running as an open source project, BSF consists of a set of Java classes which provides scripting language support within Java applications, and access to Java objects and methods from scripting languages. It provides an API that permits calling scripting language engines from within Java, as well as an object registry that exposes Java objects to these scripting language engines.
In this case, Java classes are used to extend the capabilities of scripting languages. They allow us to write powerful scripts quickly by making use of the many Java libraries available. The scripting languages are able to create Java objects and call public methods of the objects using the syntax of the scripting languages. In this way, functionality available in Java that does not exist in the scripting languages can be used in scripts.
As early examples of this technology, Netscape supports JavaScript interaction with Java applets through a technology known as LiveConnect. Microsoft's Java implementation treats every Java object (including applets) as an ActiveX control and uses its ActiveX scripting technology to allow JavaScript programs to interact with Java. Recently, the technologies are evolving in two directions:
Some of these technologies are prior to the introduction of the JSR-223 specification, and they also help in the evolution of JSR-223. Some scripting technologies are JSR-223 compatible; that is, they are used as Scripting Engines in the Java Script Framework.
There are quite a lot of scripting languages on top of Java and JVM:
Let's have a quick look at how Rhino, JRuby, and JavaFX implement the Java object scripting in their own syntax:
Rhino: Pure Java implementation of JavaScript
importPackage (java.awt);
importClass(java.awt.Frame);
var frame = new java.awt.Frame("hello");
frame.setVisible(true);
print(frame.title);
|
JRuby: Pure Java implementation of Ruby
require 'java'
frame = java.awt.Frame.new("hello");
frame.setVisible(true);
puts frame.title;
|
JavaFX: Java-based scripting language for RIA
import javafx.ui.*;
Frame {
Title: "hello"
Width: 200
Height: 50
Visible: true
}
|
In this scripting sample code, a Java object is created and its instance method is invoked. The syntax of how the scripting languages enable the use of the Java object in the scripts varies, but they share the common characteristics that they are Java-based, which makes it natural to be interoperable with Java.
Compared to pure Java, the scripting performance should be an important consideration. There is no consistent data for the Java and Script performance comparison because scripting languages themselves vary a lot. Generally speaking, the scripting performance is slower than Java since scripting languages are interpreted. We may apply the following techniques to balance the flexibility and performance of the overall solutions:
Though we don't think they would replace Java, the scripting languages are good supplements to the Java platform. The JSR-223 specification defines scripting in the Java platform, creating a flexible, extensible and consistent way to deal with scripting languages in Java. It is believed that more interaction will happen between Java and scripting languages, while both gain more popularity and developers explore their usages together in new and innovative ways.
I am indebted to the following people for their help with this article:
Carol Zhang is a member of the technical staff in the ISV Engineering department at Sun. With ten years of experience in software development and technical consulting, Carol provides technical consultation to Sun's partner software vendors in China.