1

I want to be able to pass an anonymous function from Javascript to Java using node-java (https://github.com/joeferner/node-java). Here's a sample of the Java code:

public class Example {
    public Example() {
    }

    public interface Callback {
        public void f();
    }

    public void method1(boolean flag, Callback c) {
        System.out.println("flag value: " + flag);
        if (flag) {
            System.out.println("About to call callback");
            c.f();
            System.out.println("Called callback");
        }
        else {
            System.out.println("Didn't call callback");
        }
    }
}

Here's how I want to call it from Javascript:

Example1:

var java = require('java');
java.classpath.push('test8');

var Example = java.import('Example');

var anonF = () => {
    console.log("Hello from callback!");
}

var e = new Example();
e.method1Sync(true, anonF);

This throws an error:

flag value: true
About to call callback
/Users/chris.prince/Desktop/Tests/test.js:11
e.method1Sync(true, anonF);
  ^

Error: Error running instance method
java.lang.NullPointerException
    at Example.method1(Example.java:14)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)

    at Error (native)
    at Object.<anonymous> (/Users/chris.prince/Desktop/Tests/test.js:11:3)
    at Module._compile (module.js:556:32)
    at Object.Module._extensions..js (module.js:565:10)
    at Module.load (module.js:473:32)
    at tryModuleLoad (module.js:432:12)
    at Function.Module._load (module.js:424:3)
    at Module.runMain (module.js:590:10)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)

I have also tried passing in a Javascript module as parameter, and haven't been able to get that to work either.

Example 2:

In the file "theModule.js":

exports.f = function() {
    console.log("Hello From The Module!");
};

Here's the calling Javascript code:

var theModule = require('./theModule');
var java = require('java');
java.classpath.push('test8');

var Example = java.import('Example');

var e = new Example();
e.method1Sync(true, theModule);

This second example also fails with an error:

flag value: true
About to call callback
/Users/chris.prince/Desktop/Tests/test.js:8
e.method1Sync(true, theModule);
  ^

Error: Error running instance method
java.lang.NullPointerException
    at Example.method1(Example.java:14)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)

    at Error (native)
    at Object.<anonymous> (/Users/chris.prince/Desktop/Tests/test.js:8:3)
    at Module._compile (module.js:556:32)
    at Object.Module._extensions..js (module.js:565:10)
    at Module.load (module.js:473:32)
    at tryModuleLoad (module.js:432:12)
    at Function.Module._load (module.js:424:3)
    at Module.runMain (module.js:590:10)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)

Thoughts?

Chris Prince
  • 7,288
  • 2
  • 48
  • 66
  • Are you saying that in the first example the callback is called even if you pass `false`? You're passing `true`, so of course it calls the callback. BTW, you can use `java.lang.Runnable` instead of `Callback` and you don't need the braces around the body of a Javascript arrow function. – David Conrad May 09 '17 at 03:06
  • My bad. It was an earlier version of the example where the callback was called even if I passed `false`. Specifically, when I call `e.method1(true, anonF);` or `e.method1(false, anonF);`, `anonF` gets called. I have edited my first example. – Chris Prince May 09 '17 at 11:03

1 Answers1

1

Although a little late, I'll add my answer:

Did you try using a Proxy for the Callback interface? I didn't run this code myself, but it should look something like this:

var java = require('java');
java.classpath.push('test8');

var Example = java.import('Example');
var myCallbackProxy = java.newProxy('Callback', {
  f: function () {
    console.log("Hello from callback!");
  }
});

var e = new Example();
e.method1Sync(true, myCallbackProxy);
alex3683
  • 1,460
  • 14
  • 25