I need help getting CommonJS working on Java 7 and Rhino 1.7R3.
Rhino 1.7R3 supports CommonJS modules:
And Java 7 comes bundled with Rhino 1.7R3. Unfortunately, Java 7's Rhino is a modified version, and it does not include the org.mozilla.javascript.commonjs
package:
I would like to use Rhino 1.7R3's support for CommonJS through the javax.script
API as follows:
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
engine.put("markdown", markdown);
engine.eval("var html = require('./Markdown.Sanitizer').getSanitizingConverter().makeHtml(markdown);");
return (String) engine.get("html");
(I verified through the ScriptEngineManager
that I am indeed using the Rhino 1.7R3 engine.) I thought that perhaps I could just add the following dependency to the classpath
<dependency>
<groupId>org.mozilla</groupId>
<artifactId>rhino</artifactId>
<version>1.7R3</version>
</dependency>
and CommonJS—specifically, require()
—would start working. But it doesn't. When I try to use require()
I get
Caused by: sun.org.mozilla.javascript.internal.EcmaError: ReferenceError: "require" is not defined. (<Unknown source>#2)
at sun.org.mozilla.javascript.internal.ScriptRuntime.constructError(ScriptRuntime.java:3773)
at sun.org.mozilla.javascript.internal.ScriptRuntime.constructError(ScriptRuntime.java:3751)
at sun.org.mozilla.javascript.internal.ScriptRuntime.notFoundError(ScriptRuntime.java:3836)
How do I get Java 7 to work with the full version of Rhino 1.7R3 so I can get CommonJS support?
EDIT: I found the following question, which deals with exactly the same topic:
Sanity check: Rhino does not have a require function, right?
The respondent suggests that maybe it's possible to replace the limited Rhino 1.7R3 with the CommonJS Rhino 1.7R3, but doesn't say how one might do that. That's what I'm asking about here.
This question is old, but for those coming here from Google, you can setup CommonJS support in Rhino with the following (below is just one way):
(I am just calling Rhino directly, not using Java's Scripting API)
Now you may have two files:
main.js
require-test.js
If you use
Gradle
build system. I successfully fixed this issue via adding this dependency in the project gradle file. (based on here)compile group: 'org.mozilla', name: 'rhino', version: '1.7.10'
And you have to replace imported package name from
sun.org.mozilla.javascript.internal
toorg.mozilla.javascript
in your java class file.And everything works fine.
Edit: Seems like you don't need to use JVM bootstrap classloader after all. Sun has put the default Rhino implementation classes into
package. But your loaded Rhino implementation will occupy
Thus they shouldn't collide. However if something goes wrong you can override classes in JDK with the help of bootstrap classloader. You have two options:
Basically you need to override the classpath so that your Rhino classes would take preference instead of the build-in ones.
Alternatively, if you don't have an access to ../lib/ext you can use a command-line option:
The Rhino itself does not implement Java Scripting API. In order to integrate Rhino into JDK Sun had implemented their own
ScriptEngine
andScriptEngineFactory
. Thus, if you load your ownrhino-1.7R3.jar
you won't be able to use Common JS if you load your scripts withInstead you have two options.
Implement your own
ScriptEngine
,ScriptEngineFactory
and other related classes on top of Rhino API. See how Oracle does it. Note however, that JDK sources are under GPL 2 license so you should either release your custom Script Engine wrapper for Rhino or only use those classes as a reference and don't copy the code.Use Rhino API directly. I highly recommend this approach. There are docs and examples on Mozilla website but the basic API is relatively simple:
Alternatively, I can give you a number of JS-only solutions.
Both options require you to add a js preprocessing step to your build process and may make debugging your code a bit difficult.