Can I call Java from Node.js via JNI and how?

can I call Java from Node.js via JNI? Are there any examples?


Solution 1:

You should try the node-java npm module which is a well-written wrapper over JNI.

node-jave doesn't appear to (yet) have broad adoption, but playing with it, I've been impressed with how straightforward and robust it has been.

It's as simple as:

var list = java.newInstanceSync("java.util.ArrayList");
list.addSync("item1");
list.addSync("item2");
console.log(list.getSync(1)); // prints "item2"

You can do just about anything with your embedded JVM - create objects, call methods, access fields, etc.

There is a slight impedance mismatch between Node and Java, so if you are going to interact with something complicated, I'd recommend writing most of your interactions in Java and exposing a simpler interface across the Node/Java barrier. It just makes for easier debugging that way.

--- Dave

p.s., RealWorldUseCase(tm): I worked at a place that had a pretty complex (and spaghetti-coded) protocol between multiple browser clients and a Java-based service. I wrote a pretty sweet test-harness which used jsdom to host N simulated browsers and used node-java as a wrapper around the Java service code. It was trivial to shim out the transport interfaces, both in JS for the clients, and in Java for the service, so whenever any of these things sends a message, I capture that and stick it in a queue for probabilistic delivery to the intended target (ie, I virtualized the network). In this way, I could run a full-on simulation of multiple clients interacting with and through a Java service, and run the whole thing inside a single process without any wire communication. And then I could do fun stuff like deliberately reorder message deliveries to make sure the code was resilient to timing bugs. And when a bug was discovered, I had the message orderings logged and could reproduce them to repro the bug. Oh, and the whole thing set up and ran a pretty complex scenario with a few thousand lines of logging and finished in under 1 second per run. 2-weeks well spent. Fun stuff.

RealWorld Use Case #2: selenium-inproc - a module that wraps the SeleniumRC JAR file providing a node interface to browser automation testing w/ Selenium without having to run yet another localhost service.

Solution 2:

That looks tricky. Node.JS runs on the Google Chrome JavaScript engine V8. What you will have to do is to create a V8 C++ binding (v8 c++ Crash Course shows an example) that starts a JVM and does all the JNI handling.

I think you might be better off letting a JavaServer and Node.js communicate via the network (someone wrote an example for using RabbitMQ for Java/Node.js message based communication). Here, JSON would be a great data exchange format (if you trust your Java server produces proper JSON you can just eval() it in Node).

Solution 3:

I think what you are looking for is a native extension to use as a bridge. Although I don't have an example of what you are saying, I do have an example on how to call a C++ extension using Node.JS

https://github.com/jrgleason/NodeJSArduinoLEDController