JavaScript ScriptEngine isn't working within G

2019-09-06 05:14发布

I am having an issue where I always get a 0 value returned when I try to use the ScriptEngine eval. By using Logger, I was able to determine that there are NullPointerExceptions being generated. After further inspection, it appears that GAE doesn't always return a valid script engine (if ever), because it throws an exception when you try to use it.

My code looks like:

public double myEval(String JsFormulaStr ) {
    double solutionValue = 0;
    ScriptEngineManager mgr = new ScriptEngineManager();
    ScriptEngine eng = mgr.getEngineByName("JavaScript");
    if(eng == null) {  // Added this block of code to prevent java.lang.NullPointerException...
        log.severe("Unable to get Script Engine." );
        return 0;
    }
    try {
        Object jsResults = eng.eval(JsFormulaStr);
        solutionValue = Double.parseDouble(jsResults.toString());
        return solutionValue;
    } catch(Exception e) {
        log.severe("[ERROR] in getCalculatedSolution_FromJS_ToDouble()::\n\t" +
                "Formula String is: " + JsFormulaStr + "\n\t" + e);
        return 0;
    }     
}

Everything works fine if I run it locally as a WebApp (Both in Eclipse & Netbeans. And within Tomcat & Glassfish 4.0).

Some of the strings which I tried to eval:

  • 62.0 / 100
  • 0.0 * 352.0
  • (0 - 428) * 1000
  • (0 - 597) * 1000
  • 73.0 / 100

NOTE: The 0's or 0.0's are from other evaluations which have failed in previous calls. Since this function returns 0 on error.

According to Google's JRE Class Whitelist, the ScriptEngineManager and ScriptEngine classes are allowed. So I don't understand why it isn't working as expected.

Any suggestions?

Thanks in advance,

Randy

1条回答
太酷不给撩
2楼-- · 2019-09-06 05:48

I've hit the same problem. Although the classes are whitelisted, it seems like their functionality is limited on App Engine. The code works fine on your local machine but fails when deployed to App Engine as there aren't any script engines available (hence the NullPointerException).

Luckily, you can do the same thing using the Rhino engine.

Note: this example builds on that given by Harsha R in https://stackoverflow.com/a/19828128/578821

Download the Rhino Jar and add js.jar to your classpath (you only need js-14.jar if you're using Java 1.4).

    /* Example 1: Running a JavaScript function (taken from examples) */
    String script = "function abc(x,y) {return x+y;}";
    Context context = Context.enter();
    try {
        ScriptableObject scope = context.initStandardObjects();
        Scriptable that = context.newObject(scope);
        Function fct = context.compileFunction(scope, script, "script", 1, null);
        Object result = fct.call(context, scope, that, new Object[] { 2, 3 });
        System.out.println(Context.jsToJava(result, int.class));
    } 
    finally {
        Context.exit();
    }

    /* Example 2: execute a JavaScript statement */
    script = "3 + 2 * (4*5)";
    context = Context.enter();

    try{
        Scriptable scope = context.initStandardObjects();
        Object result = context.evaluateString(scope, script, "<cmd>", 1, null);
        System.out.println(result);
    }
    finally{
        Context.exit();
    }
查看更多
登录 后发表回答