Ilya Ermolov
Ilya Ermolov

Reputation: 11

TypeError in Rhino: migration from Java 6 to Java 7

My project perfectly works on Java 6 (different updates and OS). It uses Rhino as script engine. Now we need to migrate to Java 7 and I found one issue that prevent us to do it. We have code like this:

Context.enter();
try {
    ScriptEngine js = new ScriptEngineManager().getEngineByName("js");
    final ScriptContext context = new SimpleScriptContext();
    context.setAttribute("console", new Object() {
        public void log(String out) {
            logger.info(out);
        }
    }, ScriptContext.ENGINE_SCOPE);
    js.setContext(context);
    js.eval("console.log('test')");
} catch (ScriptException e) {
    logger.error(e);
    e.printStackTrace();
} finally {
    Context.exit();
}

It works good in Java 6 but Java 7 throws exception

javax.script.ScriptException: sun.org.mozilla.javascript.internal.EcmaError: TypeError: Cannot find function log in object JSDebugTest$1@4631f1f8. (<Unknown source>#1) in <Unknown source> at line number 1
at com.sun.script.javascript.RhinoScriptEngine.eval(RhinoScriptEngine.java:224)
at com.sun.script.javascript.RhinoScriptEngine.eval(RhinoScriptEngine.java:240)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
at JSDebugTest.testJS1(JSDebugTest.java:54)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at  com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:76)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: sun.org.mozilla.javascript.internal.EcmaError: TypeError: Cannot find function log in object JSDebugTest$1@4631f1f8. (<Unknown source>#1)
at sun.org.mozilla.javascript.internal.ScriptRuntime.constructError(ScriptRuntime.java:3771)
at sun.org.mozilla.javascript.internal.ScriptRuntime.constructError(ScriptRuntime.java:3749)
at sun.org.mozilla.javascript.internal.ScriptRuntime.typeError(ScriptRuntime.java:3777)
at sun.org.mozilla.javascript.internal.ScriptRuntime.typeError2(ScriptRuntime.java:3796)
at sun.org.mozilla.javascript.internal.ScriptRuntime.notFunctionError(ScriptRuntime.java:3867)
at sun.org.mozilla.javascript.internal.ScriptRuntime.getPropFunctionAndThisHelper(ScriptRuntime.java:2343)
at sun.org.mozilla.javascript.internal.ScriptRuntime.getPropFunctionAndThis(ScriptRuntime.java:2310)
at sun.org.mozilla.javascript.internal.gen._Unknown_source__2._c_script_0(<Unknown source>:1)
at sun.org.mozilla.javascript.internal.gen._Unknown_source__2.call(<Unknown source>)
at sun.org.mozilla.javascript.internal.ContextFactory.doTopCall(ContextFactory.java:433)
at sun.org.mozilla.javascript.internal.ScriptRuntime.doTopCall(ScriptRuntime.java:3161)
at sun.org.mozilla.javascript.internal.gen._Unknown_source__2.call(<Unknown source>)
at sun.org.mozilla.javascript.internal.gen._Unknown_source__2.exec(<Unknown source>)
at sun.org.mozilla.javascript.internal.Context.evaluateReader(Context.java:1159)
at com.sun.script.javascript.RhinoScriptEngine.eval(RhinoScriptEngine.java:214)
... 30 more

Problem disappear if I extract anonymous Object to inner class. Any idea how to fix it without ScriptableObject.get (there are too many places where we create such object and some third party code we use, uses same approach)?

Upvotes: 1

Views: 3231

Answers (4)

rich
rich

Reputation: 1

Had the same problem. In my case it was not an inner class, but the top level class had a default (package level) protection. Switching to public fixed my issues ... shame it took me a couple hours to figure it out.

Upvotes: 0

Tyco
Tyco

Reputation: 131

I had exactly the same error, and after your comment "Problem disappear if I extract anonymous Object to inner class." I found that generated inner class will have default access modifier (sometimes called 'package' access modifier). Apparently, scripting API in JDK7 doesn't handle these definitions!

I use put a "static public" definition instead.

Upvotes: 1

Robert Mikes
Robert Mikes

Reputation: 1421

I also got TypeError when migrating from Java 6 to 7: my JavaScript was calling a method on a Java class which had default (package-private) visibility. Had to make the class public for it to work.

Upvotes: 0

bshapiro
bshapiro

Reputation: 1

Had a similar problem. I was passing in a private inner class and it was failing. I changed it from a private inner object to a public class and it worked just fine after the Java 7 upgrade.

Upvotes: 0

Related Questions