Search code examples
javapythonclassjythonjsr233

Jython script implementing a class isn't initialized correctly from Java


I'm trying to do something similar to Question 4617364 but for Python - load a class from python script file, where said class implements a Java interface and hand it over to some Java code that can use its methods - but calls to the object method return invalid values and printing from the initializer doesn't seem to do anything.

My implementation looks like this:

Interface:

package some.package;
import java.util.List;
public interface ScriptDemoIf {
    int fibonacci(int d);
    List<String> filterLength(List<String> source, int maxlen);
}

Python Implementation:

from some.package import ScriptDemoIf

class ScriptDemo(ScriptDemoIf):
    """ Class ScriptDemo implementing ScriptDemoIf """

    def __init__(self):
        print "Script Demo init"

    def fibonacci(self, d):
        if d < 2:
            return d
        else:
            return self.fibonacci(d-1) + self.fibonacci(d-2)

    def filterLength(self, source, maxlen):
        return [ str for str in source if len(str) <= maxlen ]

Class loader:

public ScriptDemoIf load(String filename) throws ScriptException {
    ScriptEngine engine = new ScriptEngineManager().getEngineByName("jython");
    FileReader script = new FileReader(filename);
    try {
        engine.eval(new FileReader(script));
    } catch (FileNotFoundException e) {
        throw new ScriptException("Failed to load " + filename);
    }
    return (ScriptDemoIf) engine.eval("ScriptDemo()");
}

public void run() {
    ScriptDemoIf test = load("ScriptDemo.py");
    System.out.println(test.fibonacci(30));
}

(Obviously the loader is a bit more generic in real life - it doesn't assume that the implementation class name is "ScriptDemo" - this is just for simplicity).

When the code is being ran, I don't see the print from the Python's __init__ (though if I put a print in the body of the script then I do see that), but the test variable in run() look like a valid jython "proxy object" and I get no casting errors. When I try to run the fibonacci() method I always get 0 (even if I change the method to always return a fixed number) and the filterLength() method always returns null (probably something to do with defaults according to the Java interface).

what am I doing wrong?


Solution

  • What version of jython are you using? You might have run into the JSR223 Jython bug : http://bugs.jython.org/issue1681

    From the bug description:

    Calling methods from an embedded Jython script does nothing when using JSR-223 and Jython 2.5.2rc2, while Jython 2.2.1 just works fine.