Articles / The Case For Java-Based Scr…

The Case For Java-Based Scripting Languages

Scripting languages are ubiquitous. They are used everywhere: in log parsing, triggering applications, or performing volatile operations which require frequent changes in logic. Shell script was one of the most popular languages through the end of 1980s. Then came Perl, which revolutionized the world of scripting. Later in the day, we have Python and Ruby, both pretty popular. In an organization having primarily Java skills, is it worthwhile to have your developers learn these languages?

It might not be, because it will be a costly affair, with the developers figuring out, "How will I achieve this particular functionality in XXX scripting language?" If there is one thing which the community lacks very badly in documentation, it is cross-language reference documentation. As a developer familiar with the Java language myself, I have often wondered, "Hey, this XXX functionality provided by Java -- how can I achieve it in Python?" For once, Google becomes useless!

Why think beyond the shell?

If you were living in 1980s, you probably need not have asked this question. These days, we have many scripting jobs that need to access databases, Web services, and content repositories, and, most obviously, parse XML documents. Just imagine parsing XML using sed! Well, we had one of our legacy applications doing exactly this. Suddenly, in the code you would see a call to Oracle's sqlplus, then parsing of XML using sed, then, for more complex parsing of XML, a call to a compiled Java program. It was terribly difficult to understand, and was subsequently redesigned using Groovy.

Why not Perl, Python, or Ruby?

Why dissipate organizational expertise to new languages? In all Java-based scripting languages, we can use Java classes within the script. What can be done in Java can be done here, too, and much more efficiently! For example, consider this XML snippet:

<buddies>
  <buddy>
    <name>Shanku Dada</name>
    <email>dada@foo.org</email>
  </buddy>
  <buddy>
    <name>Manivannan M</name>
    <email>mani@foo.org</email>
  </buddy>
</buddies>

To parse this in Java, you would be writing JDOM, DOM4J, SAX, or pure DOM code using JAXP APIs. But scripting languages, being poor cousins of serious languages, cannot afford so much time privilege in terms of organizational priorities. Take the example of Groovy to parse the above XML:

// friends.groovy

doc = new XmlSlurper().parse("friends.xml");
varBuddies = doc.children();

for ( buddy in varBuddies ) {
  println("Name: " + buddy.name.text() + " | Email: " +
buddy.email.text());
}

The output:

Name: Shanku Dada | Email: dada@foo.org
Name: Manivannan M | Email: mani@foo.org

You see the simplicity in parsing XML using Groovy. You show this to the client. He asks you to display only the first name. You use your Java expertise to do the string manipulation:

println "Name: " + buddy.name.text().split(" ")[0] + " | Email: " +
buddy.email.text();

with the output:

Name: Shanku | Email: dada@foo.org
Name: Manivannan | Email: mani@foo.org

All the valuable investment made in learning Java can be fully utilized in scripting. All Java classes and objects can be accessed from the scripting language, with no need to learn another syntax.

Java to script, and vice versa

The examples in this section will compile in Java 6 and above. Java 6 supports JSR 223 Scripting for the Java Platform.

Another use case which scripting languages beautifully address is plugin architectures. Many times, applications need to be given plugin architecture for users to extend and customize. All modern text editors and IDEs follow this paradigm. If scripting language support is not provided by an application, extending it means compiling a plugin, packaging it as a Jar, and deploying it in a special directory from which it will be picked by the application. Scripting reduces the compile-and-package step, greatly reducing the development timeline.

Generally, the application's plugin module loads/executes the plugins. In this case, the plugin module would need to instantiate some objects and make them available to the script engine, so that the contract between the application and the plugin script could be executed. Consider this Java code:

import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

// Actual code
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine se = sem.getEngineByExtension("js");
se.put("myvar", "Hello!");

// this throws javax.script.ScriptException, need to handle that:
se.eval("print(myvar);");

The output would be:

Hello!

To dissect this:

Java 6 comes bundled with a JavaScript scripting engine (based on Rhino). We get this engine initially in lines:

ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine se = sem.getEngineByExtension("js");

Once we get the scripting engine, object se, we can use its put(String key, Object value) method to set any variable that will be used by the script. We set the variable myvar in the Java code, which will be used in the JavaScript code. Finally, we execute the JavaScript code:

se.eval("print(myvar);");

We are calling the ScriptEngine's eval() method. This is an overloaded method which can execute script code from sources like java.io.Reader and String (which we are using in the example). In the string, we have passed the JavaScript command:

print(myvar);

, which prints the variable value set in the Java code, "Hello!".

We have seen one angle to this plugin paradigm. The next is that Objects instantiated in the script need to be accessed in the Java code. This is also pretty simple:

se.eval("myvar = 'Hello from script!';");
System.out.println(se.get("myvar"));

The output:

Hello from script!

Isn't that simple?

Some things to consider when using Java-based scripting languages

  1. Be sure that the single execution of a scripting application runs in a single JVM instance. Launching multiple JVMs would be costly, because JVM initialization is costly in terms of time.
  2. You should execute the JVM with the default memory allocation only for trivial scripting needs. Use the -Xmx##m parameter to JVM to change the default value. Our application runs using -Xmx512m.
  3. Generally, the script is triggered using a shell script, after setting up the CLASSPATH. Java 6 has the commandline tool jrunscript which removes the need for a shell script bootstrap.
  4. We needed to checkout from CVS in our script. We did not fork a new process for cvs, but implemented this logic using the Netbeans CVS library. Steps like this will keep your code pure Java and allow it to work cross-platform in the true sense of the word.

Recent comments

01 Jun 2007 19:17 Avatar sloaring

Re: Ugh. Language Chauvinism


> Why is it that Java programmers (unlike

> seemingly any other language

> programmers) want everything to be

> written in Java??

"When your only tool is a hammer, every problem looks like a nail."

s/hammer/festering whale carcass/

s/nail/magical tar pit of happiness/

Don't mind me. I'm a bitter, bitter man.

08 May 2007 08:14 Avatar overhacked

What, again, is the case?
I agree that there are many good reasons for using scripting langauges within the Java environment. Your Groovy example hints at some of these reasons. I'd point out the superior enterprise resource management of JRuby over standard (C) Ruby as another.

The bulk of your article, however, seems to make the case that one should use scripting languages in Java to keep things &quot;pure Java.&quot; Only Java-centric programmers can really take stock in this argument. Programmers who are language agnostic will not understand the benefits of JRuby, Rhino, Groovy, etc. from your arguments.

I believe there is an excellent case to be made for using the JVM in this way, and I'd like to hear it from someone with your experience.

24 Apr 2007 06:25 Avatar subwiz

Re: Abuse


> I don't consider it 'costly' when

> developers have to figure out something

> new, I tend to consider it as an

> investment for the future.

It definitely is an investment for the programmer. The average time a programmer in India stays in a job should be around 2 years (statistics from my contacts and experience). Now consider someone coming into your organization, and doing everything in some new language and then decides to leave for a better offer. if your organization's primary developer skillset is Java, how long will it take an average Java programmer to learn the new language and be productive (of course, we also have this trend in India where the Java developers will not do anything other than Java--they consider it lowly!!)? Or will you recruit a new person with that skillset just to maintain this application?

My opinion on people knowing multiple-programming-languages: it is a must. It makes them take better decisions when facing programming challenges. My argument is not against learning new languages (unfortunately, I believe the article's tone seems to suggest this--which was completely unintended). It is about the advantage of using Java expertise in your scripting environment; and about the ability to use scripting language (when running in JVM) to access Java specific services like content repositories (JSR 170) which traditionally cannot be accessed by non-Java languages; and an implicit argument against making your organizational investment going in to figure "how to do this in this language?"--I am advocating consistency, but not promoting redundancy.

> The use of ScriptEngine as a plugin

> architecture looks like an okay thing to

> do. But mixing Java and various random

> scripting languages together just

> because developers are too lazy or

> because it's too 'costly' to make them

> learn a new language seems like a

> blatant abuse of the technology. In

> fact, to me it's even worse than a shell

> script parsing XML with sed and then

> making calls to Java programs for more

> advanced XML scripting. (xml-starlet

> might have helped here).

I again disagree with your opinion on ScriptEngine. Any good technology can be abused when used irrationally. I am in no way advocating mixing some random scripting language with Java. My point is: ScriptEngine architecture allows one to gracefully support plugins in multiple languages if there be a need.

BTW, xml-starlet seems to be interesting!

21 Apr 2007 15:20 Avatar fboender

Abuse
&gt;is it worthwhile to have your developers learn

&gt;these languages?

&gt;

&gt;It might not be, because it will be a costly affair,

&gt;with the developers figuring out, &quot;How will I

&gt;achieve this particular functionality in XXX

&gt;scripting language?&quot;

Yes, heaven forbid your developers learn something new. Different programming languages tend to have different ways of solving problems, and usually there's a lot to learn from each different way. I don't consider it 'costly' when developers have to figure out something new, I tend to consider it as an investment for the future.

The use of ScriptEngine as a plugin architecture looks like an okay thing to do. But mixing Java and various random scripting languages together just because developers are too lazy or because it's too 'costly' to make them learn a new language seems like a blatant abuse of the technology. In fact, to me it's even worse than a shell script parsing XML with sed and then making calls to Java programs for more advanced XML scripting. (xml-starlet might have helped here).

21 Apr 2007 02:25 Avatar loki27

Re: Ugh. Language Chauvinism


> Why is it that Java programmers (unlike seemingly any other language programmers) want everything to be written in Java?? I so miss the days when people would use whatever language best fit the task at hand.

Not quite. It's not "everything to be written in Java" -- it's actually the opposite: the interesting thing with using other/scripting languages on the JVM is that it all runs into the JVM.

The JVM (especially 5 and 6) is extremely good at running bytecode, it has fast memory management (allocation and GC), good sandboxing (security), etc...

You can have all that with different programming languages, and even combine them, as they all produce bytecode.

Use some solid Java framework or container (Hibernate, Spring, JBoss, WebLogic, Tomcat, Jetty, XFire, Sequoia, .......) from your favourite scripting language (Groovy, JRuby, Jython, ...).

It's really the opposite of what you said: you can actually use the language that best suits your needs, and "share"/combine code from each (e.g. Java for the defensive, solid parts of your application, Groovy/GSP for the web layer, JRuby for coding unit tests, etc...).

> You have to be kidding me! I've had far worse problems writing valid XML than I ever had with Makefiles! Besides, this

Heh, yeah, I agree, writing Ant build.xml files is a pain.

There are a lot of other solutions though, GAnt (use Ant tasks but write the build file in Groovy), Maven(2), ...

> Only a java programmer would ask this question: "Why dissipate organizational expertise to new languages?"

Again, it's the exact opposite. Use several languages, depending on what suits you best for each task, and run it all on the same JVM.

> Each language has it's pros and cons.

> Perl might be great for text processing. Ruby's rails might have benefit for some small apps. Why not just use a variety

> of languages to fit whatever task is at hand?

100% ACK.

> Is it actually painful for Java programmers to know other languages?

> Unfortunately, I think the answer is that Yes, it probably is, because Java seems designed to be anti-social in that regard. To get perl to talk to the OS (and by extension other programs) is easy. Ditto for C (and by extension

C++). But, Java perversely makes talking to any other apps horrendously painful, and perhaps this breeds the attitude of Java programmers.

To some, it's most probably "everything has to be done in Java", sure. But not to everyone. I, for myself, really love Java but I also do a lot with Perl, Python, PHP, Ruby and shell.

With the scripting support in Java 6 and with projects such as Groovy, JRuby, Jython, Rhino and BeanShell, you can combine several languages. And, at least across the languages that do have support on the JVM, interoperability is excellent, even better than Perl/C or Python/C, because it's all bytecode.

(Perl/C or Python/C integration isn't much better than JNI though ;))

> But, I wish we would go back to the days when programmers had multiple language expertise. I see too many programmers these days who A. have no idea about other languages, and B. because of their ignorance cast stones at other languages with arguments of this kind: "Perl. Ugh. I hate all those $"

> That's just brilliant.

Yep, I agree.

Screenshot

Project Spotlight

Kigo Video Converter Ultimate for Mac

A tool for converting and editing videos.

Screenshot

Project Spotlight

Kid3

An efficient tagger for MP3, Ogg/Vorbis, and FLAC files.