access javascript method from java side

108 views Asked by At

I have a javascript resource and apply Rhino Script Engine to call a method from java side.

 (function( global ){

    var Result;

    (Result = function( val ) {
        this.tpl = val || '' ;
    }).prototype = {

        get: function ()
        {
            return this.tpl ;
        }

    };
} ( window ) ) ;

This is the way how i did it on java side, how can i call get method in above script ?

    @Test
    public void testCallJSMethod() throws Exception {
        String jsResource = getJSResource();

        jsEngine.put("window", "window");
        jsEngine.put("window.Result", "Result");

        jsEngine.eval(jsResource);

        Invocable inv = (Invocable) jsEngine;

        Object obj = jsEngine.get("window.Result");
        assertEquals(true, obj != null);

        //try to call get method in above script, but it doesn't work
        inv.invokeMethod(obj, "get", new Object[] {} );
    }
2

There are 2 answers

0
user3179782 On

A possible workaround for this is to store the result in a script variable and read that var with jsEngine.get("myResult");

0
Maurice Perry On

I see several issues with your code:

    jsEngine.put("window", "window");

This does not define window as a JavaScript object. You can do that as follows:

    jsEngine.eval("window={}");

In your javascript, Result is a local variable, and it will not survive the call to the outer function. You should instead assign your function to global.Result:

(function(global) {
    (global.Result = function(val) {
        this.tpl = val || '';
    }).prototype = {
        get: function()
        {
            return this.tpl;
        }

    };
})(window);

jsEngine.get(name) gets the value of a variable. If you want the value of window.Result, you must do jsEngine.eval("window.Result"), not jsEngine.get("window.Result").

But window.Result actually is a function. A constructor function actually. So to create an instance, you must do something like: jsEngine.eval("new window.Result('Hello world!!!')").

Your java function would thus become:

@Test
public void testCallJSMethod() throws Exception {
    String jsResource = getJSResource();

    jsEngine.eval("window={}");

    jsEngine.eval(jsResource);

    Invocable inv = (Invocable) jsEngine;

    Object obj = jsEngine.eval("new window.Result('Hello World!!!')");
    assertEquals(true, obj != null);

    Object res = inv.invokeMethod(obj, "get", new Object[] {} );
    assertEquals(res, "Hello World!!!");
}