There are a lot of approaches you could take, but here is the one I'd recommend for maximum cleanliness and clarity of the code on each side.
I'm assuming success
and failure
are strings, but the transformation is straightforward if they are something else.
On the Java side, make your API:
public class StuffExecutor {
public abstract static class Listener {
public abstract void success(String result);
public abstract void failure(String reason);
}
private void stuff(Listener listener) {
try {
String result = doIt();
listener.success(result);
} catch (Throwable t) {
listener.failure(t.getMessage());
}
}
public void execute(final Listener listener) {
new Thread(new Runnable() {
public void run() {
stuff(listener);
}
}).start();
}
}
Now on the JavaScript side:
function hello() {
var x = 42; // notice the closure over x in the success handler
stuffExecutor.execute(new JavaAdapter(Packages.my.package.StuffExecutor.Listener, {
success: function (result) { println("Success: " + (result + x)); },
failure: function (reason) { println("Failure: " + reason; }
}));
println("Starting to execute stuff...");
}
Like I said, other approaches could work. You could pass functions directly to your Java API (they will appear as org.mozilla.javascript.Callable
) but then your Java syntax for invoking them gets a lot more complex and messy.
Note that there was a bug in JavaAdapter in the 1.7R4 release (which has caused many people to clamor for a 1.7R5 that has not come). This should work with any other release of Rhino or with the current master on GitHub.
Note that result
and reason
would be java.lang.String
objects in this scenario, not native JavaScript strings. In your code it would make no difference but if you needed to use them later as JavaScript strings you'd probably want to convert them using String(result)
and String(failure)
.