How to access Java object functions from nashorn

961 Views Asked by At

I would like to make an interface that will allow users to supply arbitrary filter functions to process records in a Java application. I decided to use Java Scripting utilities for this, specifically nashorn and JavaScript.

My problem is that when I pass in objects to evaluate I get TypeError: org.XXX.XXX.MyClass has no such function xxx ...

public class FilterClass{
    ScriptEngine engine;
    Invocable inv;
    public FilterClass(File file){
        ScriptEngineManager manager = new ScriptEngineManager();
        engine = manager.getEngineByName("JavaScript");
        engine.eval(new FileReader(file));
        inv = (Invocable) engine;
    }
    public boolean passes(MyObject object){
        Object result = inv.invokeFunction("passes", object);
        return (Boolean) result;
    }
}

object factory definition to make MyObject

public class MyObjectFactory{

    private class MyObject{
        private final int myint;
        public MyObject(int i){
            myint = i;
        }
        public int getValue(){
            return myint;
        }
    }

    public MyObject makeObject(int i){
        return new MyObject(i);
    }
}

javascript file

function passes(o){
    if(o.getValue() > 10){
        return true;
    } else {
        return false;
    }
}
1

There are 1 best solutions below

0
Kyle On

It turns out that nashorn is unable to access functions defined in private classes like the MyObject class in the example.

Didn't want to expose my nested class so I ended up writing a wrapper class around that to expose the MyObject fields:

public class MyObjectWrapper{
    private final MyObject myobject;
    public MyObjectWrapper(MyObject o){
        myobject = o;
    }
    public int getValue(){
        return myobject.getValue();
    }
}

Then I could access the functions by wrapping:

    public boolean passes(MyObject object){
        Object result = inv.invokeFunction("passes", new MyObjectWrapper(object));
        return (Boolean) result;
    }