views:

48

answers:

2

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 could 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.

A: 

You could serialize your error object as a JSON string and then deserialize in Java.

Luis Medel
+2  A: 

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");
    }
}
cuberoot
Thanks. I'm not really concerned about finding out what went wrong. In my setup, the exceptions would be generated *on purpose* - in other words, the Javascript code would be something explicitly designed to check something out and throw an exception in some cases. What I would like would be for that exception to be useful somehow, but the ScriptEngine harness seems to just throw away the raw Javascript exception object.
Pointy