when I try to make an object of a class in java-script file which extends ScriptableObject... The following error will arise.
js: uncaught JavaScript runtime exception: TypeError: Cannot find default v开发者_JAVA技巧alue for object.”
class file is
package sumit2;
import org.mozilla.javascript.ScriptableObject;
public class Sumit extends ScriptableObject {
public String getClassName(){
return "Sumit";
}
public void foo() {
System.out.println("Sumit!!!!!!!");
}
}
Java-Script File is:-
importPackage(Packages.sumit2);
var vv=new Sumit();
print(vv.foo());
First, you have to override getDefaultValue in Sumit. This is needed to convert object to string from javascript.
package sumit2;
import org.mozilla.javascript.ScriptableObject;
public class Sumit extends ScriptableObject {
public String getClassName(){
return "Sumit";
}
public void foo() {
System.out.println("Sumit!!!!!!!");
}
@Override
public Object getDefaultValue(Class<?> typeHint) {
return toString();
}
}
And then, you will get following error message:
js: uncaught JavaScript runtime exception: TypeError: Cannot find function foo in object sumit2.Sumit@1bf6770.
**NOTE: The exception "Cannot find default value for object.” was caused when displaying exception above. The string value "sumit2.Sumit@1bf6770" is produced by calling getDefaultValue
Second, javascript cannot call java methods of objects extended from ScriptableObject. If you want to call foo from javascript, override get(String, Scriptable) like following:
package sumit2;
import jp.tonyu.js.BuiltinFunc;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
public class Sumit extends ScriptableObject {
public String getClassName(){
return "Sumit";
}
public void foo() {
System.out.println("Sumit!!!!!!!");
}
@Override
public Object getDefaultValue(Class<?> typeHint) {
return toString();
}
@Override
public Object get(String name, Scriptable start) {
if ("foo".equals(name)) {
return new Function() {
@Override
public Object call(Context cx, Scriptable scope, Scriptable thisObj,
Object[] args) {
foo();
return "Return value of foo";
}
/** ...Implement all methods of Function other than call **/
};
}
return super.get(name, start);
}
}
And you will get:
Sumit!!!!!!!
Return value of foo
I think the part
/** ...Implement all methods of Function other than call **/
is annoying. I recommend to create an adapter class which implements Function and overrides all methods of Function with empty statements.
I tried to use the code concept posted by @hoge1e3 but unfortunately it did not work for me with the latest Rhino build (1_7R5pre). However, I was able to create a Java class with methods that were invokable in JavaScript by using the annotations provided by the Rhino framework. In the end, it was actually very simple and straightforward.
As a reference, please see the examples included in the Rhino source provided by Mozilla: https://github.com/mozilla/rhino/tree/master/examples
Example class definition:
//this gives you access to the annotations needed to expose your Java methods and properties to JavaScript
import org.mozilla.javascript.annotations.JSFunction;
public class Sumit extends ScriptableObject {
public String getClassName(){
return "Sumit";
}
@JSFunction
public void foo() {
//add in the above annotation and your Java method 'foo' will now be available in JavaScript
System.out.println("Sumit!!!!!!!");
}
}
Example of converting the above class from Java to JavaScript:
//Make sure to define your Context and Scope beforehand
ScriptableObject.defineClass(scope, Sumit.class);
There is a logical error in the code: you are attempting to print a void
value: the return value of vv.foo()
.
If you change the code from what you have from print(vv.foo())
to:
vv.foo()
, or alternatively change the Java to return the String
"Sumit!!!!!!!"
and print that, I think what you have will work.
精彩评论