访问 Java 中 Java 脚本对象的字段
Access fields of a JavaScript object in Java
我正在编写一个 Scala 应用程序(应该 运行 在 Hadoop 上使用 Spark),我的用户将执行他们上传的 Java 脚本片段,我想提供对某些这些 JavaScript 用户用 Scala 编写的辅助函数(如 "make an HTTP call" 等)。所以我所做的是编写一个大的 JavaScriptHelpers
对象,然后使用
授予对该对象的访问权限
engine = scriptEngineManager.getEngineByName("JavaScript")
engine.put("jql", JavaScriptHelpers)
因此用户可以在 JavaScript 中说 jql.httpPost(...)
。使这成为可能的 Scala 代码如下所示:
def httpPost(where: String, params: Object): Try[String] = {
params match {
// JavaScript string becomes Java's String:
case body: String =>
// ...
// JavaScript object becomes Java's ScriptableObject
case obj: ScriptableObject =>
val params = convertToMap(obj)
// ...
}
}
protected def convertToMap(obj: ScriptableObject): Map[String, String] = {
(for (key <- obj.getIds().toList) yield {
(key.toString, obj.get(key) match {
case s: String =>
s
case d: java.lang.Double if d.toString.endsWith(".0") =>
d.toInt.toString
case other => other.toString
})
}).toMap
}
我发现访问存储在 JavaScript 对象中的信息的唯一方法是将它们视为 sun.org.mozilla.javascript.ScriptableObject
的实例。现在这对我的本地 OpenJDK 安装
来说就像一个魅力
java version "1.7.0_75"
OpenJDK Runtime Environment (fedora-2.5.4.2.fc20-x86_64 u75-b13)
OpenJDK 64-Bit Server VM (build 24.75-b04, mixed mode)
但是当我 运行 在我的 Hadoop 集群上使用相同的代码时,即 运行ning
java version "1.7.0_67"
Java(TM) SE Runtime Environment (build 1.7.0_67-b01)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)
然后我得到:
java.lang.NoClassDefFoundError: sun/org/mozilla/javascript/ScriptableObject
sun.org.mozilla.javascript.internal.JavaMembers.discoverAccessibleMethods(JavaMembers.java:383)
sun.org.mozilla.javascript.internal.JavaMembers.discoverAccessibleMethods(JavaMembers.java:335)
sun.org.mozilla.javascript.internal.JavaMembers.reflect(JavaMembers.java:455)
sun.org.mozilla.javascript.internal.JavaMembers.<init>(JavaMembers.java:76)
sun.org.mozilla.javascript.internal.JavaMembers.lookupClass(JavaMembers.java:847)
sun.org.mozilla.javascript.internal.NativeJavaObject.initMembers(NativeJavaObject.java:88)
sun.org.mozilla.javascript.internal.NativeJavaObject.<init>(NativeJavaObject.java:78)
sun.org.mozilla.javascript.internal.NativeJavaObject.<init>(NativeJavaObject.java:68)
...
并查看 Oracle 与 JDK 7 捆绑在一起的 Rhino 版本,可从 http://www.oracle.com/technetwork/opensource/jdk7-source-1634015.html 下载,似乎所有 sun.org.mozilla.javascript.*
类 都已移至 sun.org.mozilla.javascript.internal.*
.
现在我该如何处理这种情况?是否有任何独立于 Rhino 的方法来访问 Java 中的 JavaScript 对象的字段?或者,如何在本地环境中使用 ...javascript.ScriptableObject
时强制 Oracle JVM 使用 ...javascript.internal.ScriptableObject
?
非常感谢任何帮助。
您可以改用函数重载。
// `params` matches a JavaScript string
def httpPost(where: String, params: String): Try[String] = {
// ...
}
// `params` matches a JavaScript object
def httpPost(where: String, params: java.util.Map[_, _]): Try[String] = {
// ...
}
此解决方案适用于我的环境(Oracle JDK 8 和 OpenJDK 1.7)。
我正在编写一个 Scala 应用程序(应该 运行 在 Hadoop 上使用 Spark),我的用户将执行他们上传的 Java 脚本片段,我想提供对某些这些 JavaScript 用户用 Scala 编写的辅助函数(如 "make an HTTP call" 等)。所以我所做的是编写一个大的 JavaScriptHelpers
对象,然后使用
engine = scriptEngineManager.getEngineByName("JavaScript")
engine.put("jql", JavaScriptHelpers)
因此用户可以在 JavaScript 中说 jql.httpPost(...)
。使这成为可能的 Scala 代码如下所示:
def httpPost(where: String, params: Object): Try[String] = {
params match {
// JavaScript string becomes Java's String:
case body: String =>
// ...
// JavaScript object becomes Java's ScriptableObject
case obj: ScriptableObject =>
val params = convertToMap(obj)
// ...
}
}
protected def convertToMap(obj: ScriptableObject): Map[String, String] = {
(for (key <- obj.getIds().toList) yield {
(key.toString, obj.get(key) match {
case s: String =>
s
case d: java.lang.Double if d.toString.endsWith(".0") =>
d.toInt.toString
case other => other.toString
})
}).toMap
}
我发现访问存储在 JavaScript 对象中的信息的唯一方法是将它们视为 sun.org.mozilla.javascript.ScriptableObject
的实例。现在这对我的本地 OpenJDK 安装
java version "1.7.0_75"
OpenJDK Runtime Environment (fedora-2.5.4.2.fc20-x86_64 u75-b13)
OpenJDK 64-Bit Server VM (build 24.75-b04, mixed mode)
但是当我 运行 在我的 Hadoop 集群上使用相同的代码时,即 运行ning
java version "1.7.0_67"
Java(TM) SE Runtime Environment (build 1.7.0_67-b01)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)
然后我得到:
java.lang.NoClassDefFoundError: sun/org/mozilla/javascript/ScriptableObject
sun.org.mozilla.javascript.internal.JavaMembers.discoverAccessibleMethods(JavaMembers.java:383)
sun.org.mozilla.javascript.internal.JavaMembers.discoverAccessibleMethods(JavaMembers.java:335)
sun.org.mozilla.javascript.internal.JavaMembers.reflect(JavaMembers.java:455)
sun.org.mozilla.javascript.internal.JavaMembers.<init>(JavaMembers.java:76)
sun.org.mozilla.javascript.internal.JavaMembers.lookupClass(JavaMembers.java:847)
sun.org.mozilla.javascript.internal.NativeJavaObject.initMembers(NativeJavaObject.java:88)
sun.org.mozilla.javascript.internal.NativeJavaObject.<init>(NativeJavaObject.java:78)
sun.org.mozilla.javascript.internal.NativeJavaObject.<init>(NativeJavaObject.java:68)
...
并查看 Oracle 与 JDK 7 捆绑在一起的 Rhino 版本,可从 http://www.oracle.com/technetwork/opensource/jdk7-source-1634015.html 下载,似乎所有 sun.org.mozilla.javascript.*
类 都已移至 sun.org.mozilla.javascript.internal.*
.
现在我该如何处理这种情况?是否有任何独立于 Rhino 的方法来访问 Java 中的 JavaScript 对象的字段?或者,如何在本地环境中使用 ...javascript.ScriptableObject
时强制 Oracle JVM 使用 ...javascript.internal.ScriptableObject
?
非常感谢任何帮助。
您可以改用函数重载。
// `params` matches a JavaScript string
def httpPost(where: String, params: String): Try[String] = {
// ...
}
// `params` matches a JavaScript object
def httpPost(where: String, params: java.util.Map[_, _]): Try[String] = {
// ...
}
此解决方案适用于我的环境(Oracle JDK 8 和 OpenJDK 1.7)。