Compilation Struggles with Java 6 ScriptEngine, JavaScript, and Maven

One of the projects I am currently on is to create a Java based headless browser that I can easily control programmatically.  I have wanted this for a couple of reasons over the years, one for navigating websites when trying to scrape information and secondly for use in automated functional testing.  I love the Selenium IDE but I find that it is impossible to automate your Selenium scripts into an automated build because it requires an actual browser (e.g. Firefox, Internet Explorer, etc.) to be started and executed each time.  So I want a headless browser that will do navigation, manage the DOM model of the page, and execute JavaScript to handle AJAX calls.  (SIDENOTE:  I am planning on open sourcing this and am waiting for approval from SourceForge to move the code out there).

To support JavaScript, I wanted to just use the ScriptEngineManager found in Java 6 to execute JavaScript.  Well, one problem that I found is that it is a real pain to get at objects that have been created in an executed script.  Consider the following JavaScript example:


var foo = [“a”,”b”];

To execute that in Java 6, you would do the following:

ScriptEngineManager sm = new ScriptEngineManager();
ScriptEngine e = sm.getEngineByExtension(“js”);

String script = readFromFile(“sample.js”);


OK, so far so good.  Now let’s say you want to retrieve the value of foo from the ScriptEngine environment and iterate over the values.  The ScriptEngine class has a get method, however, this returns an Object of type, not a Java Array.  So to access values, you will need to cast the Object to a NativeArray.  Then, as you iterate the array, you might have to cast each value to a NativeObject as the get method on NativeArray only returns an object.

NativeArray a = (“foo”);

for (int i = 0; i < a.getLength(); i++) {

  System.out.println(a.get(i, a));


Now your code is relying on a Sun internal class and not a base JDK class.  The appropriate classes exist in the $JAVA_HOME/lib/rt.jar file.  Unfortunately, this jar file is NOT used by default when running javac.  So to get my code to compile, I had to use the rt.jar in my bootclasspath.  Since I am using Maven 2.0 as my build system, I had to add the following to the pom.xml where I am defining my compiler

          <verbose />

This put the rt.jar into the bootclasspath when building and allowed my code to compile.  What I had hoped would be a simple task turned out to be a real ordeal.

Using the classes is very, very ugly and has the added distraction that it is hard to build and will be hard to maintain.  I do not see a way around the problem and I have found other people having similar problems working with the scripting API.  If anyone has a better approach, I am all ears.

4 thoughts on “Compilation Struggles with Java 6 ScriptEngine, JavaScript, and Maven

  1. Rob,

    I know what you’re experiencing as far as being able to consistently share Java objects with a script interpreter.

    Two possible solutions. First, embed Rhino directly using the Rhino ScriptEngine implementation. That way, you’re dependent at build time on the Mozilla js.jar rather than the Sun rt.jar. I posted a more-detailed explanation on my reply to your comment on my blog,

    The second technique I’ve used to avoid adding rt.jar to a build classpath is to use Class.forName trickery. Code the “” class as a string in Class.forName and cast the new instance to a generic super type that isn’t in rt.jar. It sounds like this technique might not work for you, short of casting the instance to an Object, if the NativeArray class can’t be cast somehow to a java.lang.reflect.Array type or equivalent.

    Good luck.


  2. Thanks, I had this problem while using Ant. The solution is similar, simply specify the “bootclasspath” attribute of the Javac task.

Comments are closed.