【问题标题】:Invoking function on Java subclass in Nashorn在 Nashorn 中调用 Java 子类的函数
【发布时间】:2017-04-12 18:51:29
【问题描述】:

我有一个看起来像这样的 JavaScript 脚本:

function run(database) {
    var result = database.query("query", "some resource name");
    //operations on result
    return result;
}

我有 Java 代码来执行类似这样的脚本:

public Object execute(String script, Database database) {
    NashornScriptEngineFactory nsef = new NashornScriptEngineFactory();
    ScriptEngine engine = nsef.getScriptEngine();
    try {
        engine.eval(script);
        Invocable invocable = (Invocable) engine;
        return invocable.invokeFunction("run", database);
    } catch(ScriptException e) {
        throw new RuntimeException(e);
    }
}

Database 是一个包含多个方法定义的接口,但 包含query 方法。我用Database 的实现调用execute,调用它DatabaseImpl确实query 方法。这将是多态的,并且脚本应该知道传递给它的 Database 实例上可用的方法。我决定不使用泛型,因为它们在运行时会被删除,所以 JavaScript 无论如何都无法使用它们,所以由脚本编写者来获得正确的类型。

但是,当我运行此代码时,出现以下异常:

javax.script.ScriptException: TypeError: database.query is not a function in <eval> at line number 25

基本上,要点是,我有一个实现接口的对象,并调用特定实例实现的方法,但不是接口定义的一部分。我的印象是这应该仍然有效,但它没有。对我来说,我需要在脚本中进行子转换才能访问 query 方法(这甚至可能吗?),所以我为什么会收到这个错误?是因为接口定义中没有该方法吗?有解决办法吗?

谢谢。

【问题讨论】:

    标签: javascript java java-8 nashorn


    【解决方案1】:

    这是主类:

    package so;
    import java.io.InputStreamReader;
    import javax.script.Invocable;
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    
    public class Nashorn {
        public static void main(String[] args) {
            try (InputStreamReader in = resource()) {
                ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
                engine.eval(in);
                Invocable invocable = (Invocable) engine;
                Database database = new DatabaseImpl();
                Object x = invocable.invokeFunction("run", database);
                System.out.println(x);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        private static InputStreamReader resource() throws Exception {
            return new InputStreamReader(Nashorn.class.getResourceAsStream("db.js"), "utf-8");
        }
    
    }
    

    接口与实现

    package so;
    
    public interface Database {
        void connect();
    }
    
    package so;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    public class DatabaseImpl implements Database {
    
        @Override
        public void connect() {
            System.out.println("Connecting");
        }
    
        public List<?> query(String ... stmt){
            List<String> lst = new ArrayList<>(); 
            lst.addAll(Arrays.asList(stmt));
            lst.addAll(Arrays.asList("A","B","C"));
            return lst;
        }
    
    }
    

    javascript 文件 (so/db.js)

    function run(database) {
        var result = database.query("query", "some resource name");
        //operations on result
        return result;
    }
    

    运行结果:

    [query, some resource name, A, B, C]
    

    它基本上可以工作。

    【讨论】:

    • 那么可能是PEBCAC...我会继续寻找。感谢您查看此内容。
    猜你喜欢
    • 2019-04-16
    • 2014-12-19
    • 1970-01-01
    • 1970-01-01
    • 2016-01-10
    • 1970-01-01
    • 2013-10-20
    • 1970-01-01
    相关资源
    最近更新 更多