Is it possible to communicate stuff from Rhino up to Java via an exception?
Using the JDK 6 ScriptEngine
mechanism, anything that goes wrong during an "eval" or "invokeMethod" or whatever results in a ScriptException
being thrown back to the invoking Java environment. As far as I've been able to tell by experimentation and source code reading, the best I can do to get information back from Javascript when my Javascript code wants to throw an exception is to throw a string. That string shows up in the "getMessage" return value from the ScriptException
object. Not pretty.
It seems like it would be nice to be able to:
if (somethingWrong) {
throw { error: Errors.INVALID_SOMETHING, context: whatever() };
}
from Javascript, and then the Java code co开发者_Python百科uld somehow get at that object. I fear however that given the current implementation of the Rhino ScriptEngine
wrapper, that's just not possible. If anybody knows a trick that does work, however, I'd love to see it.
Rhino does have poor support for Exceptions, they arent as usable as or helpful as they are in other Scripting engines like Groovy or JRuby.
To help you debug problems, I think you can use this trick. Rhino adds a non standard property to the Error object which you can access to print out some information about the Error.
try {
someCode()
}
catch(e) {
if(e.rhinoException != null)
{
e.rhinoException.printStackTrace();
}
}
You could also use Bindings to indicate that something went wrong?
I understand what you are looking for now. Its not pretty, in fact its terrible, but you can get access to the underlying JavaScriptException and then get hold of the value where you threw the Exception.
package test;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import sun.org.mozilla.javascript.*;
public class Main {
private static ScriptEngineManager mgr = new ScriptEngineManager();
private static ScriptEngine engine = mgr.getEngineByName("JavaScript");
public static void main(String... args) {
System.out.println("START");
try {
engine.eval("throw { error: \"cheese\", context: \"payload\" };");
} catch (ScriptException e) {
JavaScriptException jse = (JavaScriptException)e.getCause();
Object obj = jse.getValue();
ScriptableObject so = (ScriptableObject)obj;
System.out.println(so.get("error", so));
System.out.println(so.get("context", so));
}
System.out.println("END");
}
}
You could serialize your error object as a JSON string and then deserialize in Java.
FWIW, I think it would also be hugely useful if you could throw a Java exception object and have that propagate up the stack. For instance, to adapt the code from above:
try {
engine.eval("throw new java.lang.IllegalArgumentException( 'no cookie!' )" );
}
catch (ScriptException e) {
Throwable cause = e.getCause();
if ( cause != null && cause instanceof IllegalArgumentException ) {
// ...react explicitly
}
else {
// ...react generically
}
精彩评论