【发布时间】:2016-08-09 23:37:44
【问题描述】:
我有一个类似下面的 java 类
public class StaticBean {
public static String returnString(int num){
String json = "[{\"name\" : \"John Doe\", \"age\" : 30}]";
return json;
}
}
在下面的测试中,我有两个引擎实例。
在执行时,我发现无法将绑定实例复制到另一个实例上并将其用于在同一引擎或不同引擎中执行。即使我复制,如果我使用相同的引擎/绑定,结果与我得到的结果不匹配。
@Test
public void testParsingStringObjects() {
Bindings b = engine.createBindings();
b.put("ndb", getBindingObject(StaticBean.class, engine));
engine.setBindings(b, ScriptContext.ENGINE_SCOPE);
String source = "print('Definition in engine instance 1');"
+ "var SysU = {};\n"
+ "SysU.returnObject = function returnObjectJS(){\n"
+ "var string = ndb.returnString(1);\n"
+ "return JSON.parse(string);\n" + "}\n"
+ "SysU.returnString = function returnStringJS(){\n"
+ "var string = ndb.returnString(1);\n"
+ "print('String returned by the java function SysU.returnString() '+string);\n"
+ "return string;\n" + "};\n"
+ "print('====================Using the same engine instance for execution====================');\n"
+ "(function (){" + "var json = {};\n"
+ "print(\"String Returned in Caller SysU.returnString(): \"+SysU.returnString());\n"
+ "print(\"Object Returned in Caller SysU.returnObject(): \"+SysU.returnObject());\n"
+ "print(\"**Stringified Object Returned in Caller JSON.stringify(SysU.returnObject()): \"+JSON.stringify(SysU.returnObject()));\n"
+ "print('Adding the object in another ( json.ext = SysU.returnObject();) ...');\n"
+ "json.ext = SysU.returnObject();\n"
+ "print(\"Added JSON object which is stringified to display JSON.stringify(json): \"+JSON.stringify(json));\n" + "})();";
try {
engine.eval(source);
Bindings oldEngineBindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
Bindings localBindings = engine2.getBindings(ScriptContext.ENGINE_SCOPE);
Bindings newBindings = engine.createBindings();
oldEngineBindings.put("fileName","oldEngine");
localBindings.put("fileName","localEngine");
newBindings.putAll(oldEngineBindings);
newBindings.putAll(localBindings);
oldEngineBindings.putAll(localBindings);
ScriptContext ctxt = new SimpleScriptContext();
ctxt.setBindings(oldEngineBindings, ScriptContext.ENGINE_SCOPE);
engine.setContext(ctxt);
engine.eval(""
+ "print('====================Using the same engine with original binding ====================');\n"
+ "(function (){" + "var json = {};\n"
+ "print(\"String Returned in Caller SysU.returnString(): \"+SysU.returnString());\n"
+ "print(\"Object Returned in Caller SysU.returnObject(): \"+SysU.returnObject());\n"
+ "print(\"**Stringified Object Returned in Caller JSON.stringify(SysU.returnObject()): \"+JSON.stringify(SysU.returnObject()));\n"
+ "print('Adding the object in another ( json.ext = SysU.returnObject();) ...');\n"
+ "json.ext = SysU.returnObject();\n"
+ "print(\"Added JSON object which is stringified to display JSON.stringify(json): \"+JSON.stringify(json));\n" + "})();");
ctxt.setBindings(newBindings, ScriptContext.ENGINE_SCOPE);
engine.setContext(ctxt);
engine.eval(""
+ "print('====================Using the same engine with copied new binding ====================');\n"
+ "(function (){" + "var json = {};\n"
+ "print(\"String Returned in Caller SysU.returnString(): \"+SysU.returnString());\n"
+ "print(\"Object Returned in Caller SysU.returnObject(): \"+SysU.returnObject());\n"
+ "print(\"**Stringified Object Returned in Caller JSON.stringify(SysU.returnObject()): \"+JSON.stringify(SysU.returnObject()));\n"
+ "print('Adding the object in another ( json.ext = SysU.returnObject();) ...');\n"
+ "json.ext = SysU.returnObject();\n"
+ "print(\"Added JSON object which is stringified to display JSON.stringify(json): \"+JSON.stringify(json));\n" + "})();",newBindings);
ctxt.setBindings(oldEngineBindings, ScriptContext.ENGINE_SCOPE);
engine2.setContext(ctxt);
engine2.eval(""
+ "print('====================Using a different engine instance with original binding ====================');\n"
+ "(function (){" + "var json = {};\n"
+ "print(\"String Returned in Caller SysU.returnString(): \"+SysU.returnString());\n"
+ "print(\"Object Returned in Caller SysU.returnObject(): \"+SysU.returnObject());\n"
+ "print(\"**Stringified Object Returned in Caller JSON.stringify(SysU.returnObject()): \"+JSON.stringify(SysU.returnObject()));\n"
+ "print('Adding the object in another ( json.ext = SysU.returnObject();) ...');\n"
+ "json.ext = SysU.returnObject();\n"
+ "print(\"Added JSON object which is stringified to display JSON.stringify(json): \"+JSON.stringify(json));\n" + "})();");
} catch (ScriptException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
这是一种可接受的行为吗?还是错误?我应该能够复制绑定并在同一引擎或不同引擎实例的不同范围内使用它们并产生相同的结果。
我正在 Java8u101 上进行测试
运行测试时的结果。 当绑定或引擎实例更改时,ReturnObject() 函数似乎失败了。
Definition in engine instance 1
====================Using the same engine instance for execution====================
String returned by the java function SysU.returnString() [{"name" : "John Doe", "age" : 30}]
String Returned in Caller SysU.returnString(): [{"name" : "John Doe", "age" : 30}]
Object Returned in Caller SysU.returnObject(): [object Object]
**Stringified Object Returned in Caller JSON.stringify(SysU.returnObject()): [{"name":"John Doe","age":30}]
Adding the object in another ( json.ext = SysU.returnObject();) ...
Added JSON object which is stringified to display JSON.stringify(json): {"ext":[{"name":"John Doe","age":30}]}
====================Using the same engine with original binding ====================
String returned by the java function SysU.returnString() [{"name" : "John Doe", "age" : 30}]
String Returned in Caller SysU.returnString(): [{"name" : "John Doe", "age" : 30}]
Object Returned in Caller SysU.returnObject(): [object Object]
**Stringified Object Returned in Caller JSON.stringify(SysU.returnObject()): [{"name":"John Doe","age":30}]
Adding the object in another ( json.ext = SysU.returnObject();) ...
Added JSON object which is stringified to display JSON.stringify(json): {"ext":[{"name":"John Doe","age":30}]}
====================Using the same engine with copied new binding ====================
String returned by the java function SysU.returnString() [{"name" : "John Doe", "age" : 30}]
String Returned in Caller SysU.returnString(): [{"name" : "John Doe", "age" : 30}]
Object Returned in Caller SysU.returnObject(): [object Object]
**Stringified Object Returned in Caller JSON.stringify(SysU.returnObject()): undefined
Adding the object in another ( json.ext = SysU.returnObject();) ...
Added JSON object which is stringified to display JSON.stringify(json): {}
====================Using a different engine instance with original binding ====================
String returned by the java function SysU.returnString() [{"name" : "John Doe", "age" : 30}]
String Returned in Caller SysU.returnString(): [{"name" : "John Doe", "age" : 30}]
Object Returned in Caller SysU.returnObject(): [object Object]
**Stringified Object Returned in Caller JSON.stringify(SysU.returnObject()): undefined
Adding the object in another ( json.ext = SysU.returnObject();) ...
Added JSON object which is stringified to display JSON.stringify(json): {}
编辑:-
找到这个帖子https://bugs.openjdk.java.net/browse/JDK-8067642。这提到了关于外部对象是 ScriptObjectMirror 实例的一些事情。我使用 typeof 运算符来显示在失败和成功的情况下返回的对象类型,并且两次都是 ScriptObjectMirror 但如果我在上下文中使用原始绑定对象,则 stringify 会按预期工作。
编辑 2:-
添加了一个非常简单的测试来演示上述内容。有点像上面的 TLDR :)。执行下面的代码展示了绑定对象上的 putAll() 并没有像我们预期的那样工作。
@Test
public void testParsingObjects() throws ScriptException {
String source = "var Func = {};\n"
+ "Func.getJavaScriptObject = function(){"
+ "var jsString = '{\"foo\":\"bar\"}';\n"
+ "return JSON.parse(jsString);"
+ "};";
String executor = "(function(){ "
+ "var obj = Func.getJavaScriptObject();"
+ "print(JSON.stringify(obj));"
+ " })();";
System.out.println("Executing source...");
engine.eval(source);
System.out.println("\nUsing the same binding instance and engine\n");
engine.eval(executor);
Bindings originalBinding = engine.getBindings(ScriptContext.ENGINE_SCOPE);
Bindings copiedBinding = engine.createBindings();
copiedBinding.putAll(originalBinding);
System.out.println("\nUsing the copied binding instance and engine\n");
engine.eval(executor,copiedBinding);
}
执行结果。
Executing source...
Using the same binding instance and engine
{"foo":"bar"}
Using the copied binding instance and engine
undefined
【问题讨论】:
标签: javascript java nashorn