3

How would one include a script "Bar" from within another script "Foo" that is being evaluated by the Rhino Engine, running in Java.

IE, setup the script engine like this in Java:

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("javascript");
BufferedReader br = new BufferedReader(new FileReader(new File("Foo.js")));
engine.eval(br);

... and put the following in Foo:

load(["Bar.js"])

According to Rhino shell documentation, that's the way to do it. But when running from Java, it's clearly not implemented:

javax.script.ScriptException: sun.org.mozilla.javascript.internal.EcmaError: ReferenceError: "load" is not defined.

@Phillip:

Thanks for the creative response. Your solution as is doesn't quite work because eval doesn't make the parsed function available unless the Invocable interface is used. Further, it doesn't work in cases where the Java code is not accessible. I elaborated on your workaround and created something that will work in pure JS:

First create an engine, exposing the Invocable interface:

var engine = new Packages.javax.script.ScriptEngineManager().getEngineByName("javascript");
engine = Packages.javax.script.Invocable(engine);

Then "load()" the script(s)

engine.eval(new java.io.FileReader('./function.js'));

At this point, functions can be evaluated with:

engine.invokeFunction("printHello", null);
1
  • Note: This is not executing in Rhino shell, nor the browser. Commented Sep 10, 2012 at 18:21

1 Answer 1

5

I managed to do it by passing the engine to itself and then calling eval() on it inside the Javascript code:

Java code:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
engine.put("engine", engine);
engine.eval(new FileReader("test.js"));

test.js:

engine.eval(new java.io.FileReader('function.js'));
printHello();

function.js:

function printHello() {
    print('Hello World!');
}

output:

Hello World!

I don't know if that's the most elegant way to do it, but it works.

Sign up to request clarification or add additional context in comments.

3 Comments

"Yo, dawg, I heard you like ScriptEngines, so I put an engine in your engine, so you can eval while you eval!"
Thanks Philipp, this will work for the most part. (See my edit above)
What you did different than me is that you create a new ScriptEngine in the Javascript part. I passed the ScriptEngine I have in the Java part using engine.put() before calling eval to jump into the Javascript code so I have the engine already available. I tested it - it works flawlessly. This, of course, assumes that you have control over the Java part of the application. When you are writing scripts for someone elses application, creating the ScriptEngine in the Javascript part is the only way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.