I\'m using the javax.script.* package of the JDK. Specifically, I\'m using the JavaScript engine, which, from what I\'ve read, seems to be based on a Mozilla-developed Java
You didn't explain why you were doing this, but I was emulating a program that interacts with an end user, like this:
print('Hello!');
a=Number(input('enter a number'));
b=Number(input('and another number'));
print('the sum of '+a+' plus '+b+' is '+(a+b))
I've got it working just by creating a print and an input function in javascript that checks for program state.
you can see a demo here.
it's all written in javascript so you can look at the source code with any browser.
Hope it helps
Alright, it took me many hours of digging through documentation, tutorials, and examples, and also posting on here and on the Rhino Google Group, but I've managed to compile a working solution. Since there seems to be no complete example, I'll post my findings here for anyone who stumbles across this in the future.
Actually, my findings are probably too long to post here, so I decided to write up a tutorial on my blog:
http://www.joshforde.com/blog/?p=7
Hope that helps someone. As far as I know, this is the only complete Rhino tutorial that shows how to do all of the following: initialize Rhino, load a script from a JavaScript (*.js) file, automatically bind all of the functions in a particular Java class (e.g. ScriptFunctions) as global functions in JavaScript, and finally call a JavaScript function and handle continuations for that call.
Basically, the problem was that I needed to first download the Mozilla Rhino source code (because the version packed in with the JDK is outdated and doesn't support continuations), rewrite all of my code to use the official Rhino package's syntax (it is very different from JDK's ScriptingEngine syntax), write a Java function that throws a ContinuationPending exception and bind it to JavaScript so JavaScript can call it (because throwing a ContinuationPending directly from JavaScript results in a JavaScriptException being thrown, not a ContinuationPending being thrown, and even trying to call getCause() on that JavaScriptException results in null), and then in my Java code that calls my JavaScript function ("myJSFunction" in my original example), have try/catch blocks to check for a ContinuationPending (which is an exception), and then use that ContinuationPending later to resume the script.
Phew. It was tough, but it's all worth it now.
You could use wait/notify:
public final class Pause {
private final Object lock = new Object();
public void await() throws InterruptedException {
synchronized (lock) {
lock.wait();
}
}
public void resumeAll() {
synchronized (lock) {
lock.notifyAll();
}
}
}
Usage:
final Pause pause = new Pause();
class Resumer implements Runnable {
@Override public void run() {
try {
Thread.sleep(5000);
pause.resumeAll();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
new Thread(new Resumer()).start();
SimpleBindings bindings = new SimpleBindings();
bindings.put("pause", pause);
String script = "print('Hello, ');\n"
+ "pause.await();\n"
+ "println('ECMAScript!');\n";
new ScriptEngineManager().getEngineByName("ECMAScript")
.eval(script, bindings);
This is a relatively simplistic solution as you don't mention any other constraints. wait() causes the thread to block, which would not be acceptable in all environments. There is also no easy way to identify what threads are waiting on the Pause
instance if you want to run scripts concurrently.
Note: the InterruptedException
on await()
should be handled either by the caller or by doing something more sensible in await()
.