The state of importing node.js modules into Java
As I noticed in previous article about script management I’d like to support script sharing in The Console. This topic automatically brings idea of supporting Node.js modules. Nashorn doesn’t provide any kind of module import/export mechanism like CommonJS. However, it’s doable to provide custom require() and module.exports. But is it possible to really import Node.js modules or anything from npm?
Node.js environment
Nashorn includes functions like load()
or loadWithNewGlobal()
to load, interpret and execute external .js files. However, those functions execute loaded code in Nashorn environment and not in Node.js environment. Node.js includes filesystem, sockets and few other native things that depend on operating system so modules that depend on Node.js API won’t run properly in Nashorn.
There are two approaches to bring communication between Node.js and JVM:
- reimplementation of Node.js API (mostly, I/O modules) inside of Nashorn environment
- create a bridge between Node.js and JVM but by throwing out Nashorn entirely
It’s worth to note that there existed some projects which wanted to overcome this problem:
- Avatar.js - this one takes the first approach
- Nodyn - about this one, I’m not sure but looks like it’s still approach no. 1
Nodyn
On Nodyn GitHub Project we can read “This project is no longer being actively maintained.” Later on “Nodyn doesn’t yet have an initial release.”
I didn’t want to disqualify it, so I looked how it works. Nodyn depends on old Node.js version v0.12. Also, it’s built on top of DynJS Runtime which is also not maintained anymore. Though, between forks I’ve found nashorn branch which moves project from DynJS to Nashorn. Two different maintainers kept updating it for some time:
But is it worth even looking at when almost nobody seems to be interested in this project?
Avatar.js
This project is simply dead. It required to include native libraries for different operating systems. The project was supposed to be maintained by Oracle (which is a developer of Java, currently).
An interesting part is how Avatar.js works:
It creates it’s own layer on top of Nashorn by implementing Node.js API inside of Nashorn JS context and allowing to communicate between different Java Threads to modify same data. Looks cool. However, reimplementation of Node.js API sounds as the only way to connect Nashorn with Node.js and Oracle threw it away.
The other way
By bridge between Node.js and JVM I would be thinking about a special Node.js module that connects to JVM app and awaits events of execution. Then sends results back. Connection could be made using sockets. The minus of this approach is a need to install Node.js module globally to run scripts in Node.js context from Java app. Sounds much more stable than implementing whole Node.js API in context of Java API but I haven’t seen anyone done such library. However, for a reference there’s something near this: node-jvm.
Alternatives to Nashorn
Already told about Avatar.js which is built on top of DynJS - an alternative to Nashorn.
- Rhinodo - based on Mozilla Rhino but seems to be not maintained anymore
- RingoJS - actually, seems a lot better
Nashorn is an internal implementation so it’s supposed to have better performance. But I don’t care, I’m not going to code fast-pacing games inside The Console. RingoJS looks as a good alternative to Nashorn.
Modules at least, please
Node.js environment and npm eco-system contain many libraries so, if sticking to Nashorn, I thought it would be reasonable to bring some connection, even for small modules like left-pad :)
There are a couple of links about simulating CommonJS or RequireJS:
- jvm-npm @ GitHub
- jjsml: a Module Loader for the Nashorn JavaScript Shell
- Running a no-dependencies Node module in Java
- nashorn-commonjs-modules @ GitHub
- commonjs-modules-javax-script @ GitHub
- js-module-loader @ GitHub
- “How can I use CommonJS modules with Oracle’s new Nashorn JS Engine?” @ StackOverflow
Final Judgement
The aim here is to support some part of npm modules in The Console and module mechanism itself. But the most important thing is to support some kind of modules - if not similiar to npm then custom. As development of The Console goes, I’m going to look into RingoJS and if that doesn’t satisfy my usage requirements then I’m going to simulate CommonJS.
Resources:
- Frequently asked questions about Nashorn and Node.js
- Node.js modules
- Running Node.js applications on the JVM with Nashorn and Java 8
- DynJS
- jvm-npm
- node-jvm
- Esprima - ES6 implementation that works with Nashorn and Rhino
- Is Oracle’s Avatar dead?