【发布时间】:2019-01-16 07:05:33
【问题描述】:
大家好,
我正在编写一个应用程序来根据存储在旧 .dbf 文件中的信息进行计算,这些信息来自用于 MS-DOS 系统的旧 fox-pro,这些计算会生成用于新簿记 - ERP 系统的日记帐分录;用户应该能够即时添加/删除/修改条目的生成。所以,我的解决方案是使用 Nashorn 脚本引擎:我在应用程序设置中定义了一个文件夹,然后应用程序扫描该文件夹内的所有 .js 文件,该文件夹扩展了一个生成条目的抽象类(Totalizer),瞧。
一切听起来都不错,只是它不起作用 B-)
Totalizer抽象类的源码是:
public abstract class Totalizer {
private List<Expense> expenses;
private List<Employee> distribution;
/**
*
* @return Id of the totalizer.
*/
public abstract String getId();
/**
* @return Descriptive title of the totalizer.
*/
public abstract String getTitle();
/**
* Creates the JournalEntry based upon a single DBF record.
*
* @param record dbf record.
* @return List of journal entries.
* @throws java.lang.Exception if any exception is thrown.
*/
public abstract List<JournalEntry> totalize(
DbfRecord record) throws Exception;
public void setExpenseMapping(List<Expense> expenses) {
this.expenses = expenses;
}
public void setDistribution(List<Employee> distribution) {
this.distribution = distribution;
}
}
然后,我有脚本文件,我分享其中一个,因为它们都相似:
/**
* Vacations expenses entry:
*/
var BenefVacaciones = Java.extend(Totalizer, {
getId : function(){
return "diar.BenefVaca";
},
getTitle : function(){
return "Beneficios: Vacaciones.";
},
totalize : function(record){
//TODO: implement this method.
return null;
}
});
/*
* Creates a new instance of BenefVacaciones.
*/
function createInstance() {
return new BenefVacaciones();
}
然后,“加载”脚本的类是 Task 的实现,它执行以下操作:
//Loads a script and returns totalizer implementation.
public Totalizer loadScript(File aFile) throws IOException, ScriptException{
//creates the engine.
var engine = new NashornScriptEngineFactory().getScriptEngine();
//reads script from FileReader
try(var reader = new FileReader(aFile)){
var obj = engine.eval(reader);
if(obj instanceof Invocable){//if obj is invocable
var inv = (Invocable)obj;//casts to invocable
var ret = inv.invokeFunction("createInstance");//invoke
if(ret instanceof Totalizer){//if invoked function is Totalizer
return (Totalizer)ret;//return that totalizer
}else if(ret == null){//if invoked function returns null
throw new NullPointerException("return value is null.");
}else{//if returns non-null value but isn't Totalizer
throw new ScriptException("Function createInstance won't return Totalizer");
}
}else if(obj == null){//WATCH: If engine.eval returns null
throw new NullPointerException("engine.eval returns null.");
}else{//If engine.eval returns non-invocable value.
throw new ScriptException("Cannot get invocable object.");
}
}
}
当然,这段代码应该抛出一个
ScriptException, ReferenceError: "Totalizer" 未在
中定义 在线...
但有趣的是,如果我在 .js 脚本文件中添加以下行:
var Totalizer = Java.type('com.fossc.diar.onfalo.jsapi.Totalizer');
然后,engine.eval 返回 null,代码执行落入带有注释“WATCH:如果 engine.eval 返回 null”的 Totalizer 行,当我希望获得一个 Invocable 对象或任何其他对象的实例时。 没有抛出异常,所以我没有任何信息。 我还尝试在引擎声明后立即在 loadScript 方法中添加以下行:
engine.put(
"Totalizer",
jdk.dynalink.beans.StaticClass.forClass(Totalizer.class));
但它返回 null。还尝试添加一个始终返回 true 的类过滤器,但这都不起作用。我一直在寻找解决方案,但似乎没有任何效果,当我在任何脚本中使用 Java.type() 时,engine.eval 返回一个空对象而不是 Invocable 实例,甚至测试 engine.eval("var x = Java.type(\'java.lang.String\');") 返回 null。
出于用户界面的原因,我从 JavaFX 任务实现中调用 loadScript 函数,所以我发现了 https://stackoverflow.com/questions/33945507/java-nashorn-classnotfoundexception-java-type 的帖子,并且我尝试将 currentThread.contextClassLoader 设置为 Totalizer.class.getClassLoader()
我做错了吗?
我正在使用以下软件:
- IDE:Apache Netbeans 9.0(构建 incubator-netbeans-release-334-on-20180708)。
- 项目类型:JavaFX 应用程序项目。
- 甲骨文 JDK 10
- java --version: java 10.0.1 2018-04-17
- Java(TM) SE 运行时环境 18.3(内部版本 10.0.1+10)
- Java HotSpot(TM) 64 位服务器 VM 18.3(内部版本 10.0.1+10,混合模式)
- javac --version: javac 10.0.1
- java --version: java 10.0.1 2018-04-17
- S.O.:Manjaro Linux 17.1.11 Hakoila。
【问题讨论】:
标签: javascript java nashorn