Java 7 + Rhino 1.7r3 Support For Commonjs Modules?
Solution 1:
Edit: Seems like you don't need to use JVM bootstrap classloader after all. Sun has put the default Rhino implementation classes into
sun.org.mozilla.javascript.*
package. But your loaded Rhino implementation will occupy
org.mozilla.javascript.*
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.
- Simply put the rhino-1.7R3.jar to your-JRE-path\lib\ext. This way Rhino jar will be added to Java Bootsrap classloader and will be loaded before the build-in JavaScript jar.
Alternatively, if you don't have an access to ../lib/ext you can use a command-line option:
-Xbootclasspath/a:path/to/rhino-1.7R3.jar
The Rhino itself does not implement Java Scripting API. In order to integrate Rhino into JDK Sun had implemented their own ScriptEngine
and ScriptEngineFactory
. Thus, if you load your own rhino-1.7R3.jar
you won't be able to use Common JS if you load your scripts with
ScriptEngineManagermgr=newScriptEngineManager();
ScriptEngineengine= mgr.getEngineByName("JavaScript");
Instead 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:
// Execution environment for Rhino// there should be only one context in a giver threadContextcx= Context.enter(); // Object.prototype, Function prototype, etc.Scriptablescope= cx.initStandardObjects(); // Execute script from a given java.io.ReaderObjectresult= cx.evaluateReader(scope, reader, 0, null); // If returning result isn't sufficient for your needs// you can do something like this:ObjectsomeVar= scope.get("someVar"); // Don't forget to close the context when you're done Context.exit();
Alternatively, I can give you a number of JS-only solutions.
- Take a look at Browserify. It's a JavaScript preprocessor which will combine your source code into a single bundle.
- Rewrite your modules so that they use either AMD or UMD and then combine them with r.js tool.
Both options require you to add a js preprocessing step to your build process and may make debugging your code a bit difficult.
Solution 2:
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)
List<URI> paths = Arrays.asList(newURI[] { newFile("js/require/paths/here").toURI() });
Contextctx= Context.enter();
Scriptablescope= ctx.initStandardObjects();
newRequireBuilder()
.setModuleScriptProvider(newSoftCachingModuleScriptProvider(
newUrlModuleSourceProvider(paths, null)))
.setSandboxed(true)
.createRequire(ctx, scope)
.install(scope);
//// now you can ctx.evaluateString(...) and use require()//
Context.exit();
Now you may have two files:
main.js
require('require-test.js')()
require-test.js
module.exports = function() {
java.lang.System.out.println('The CommonJS require function works!')
}
Solution 3:
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
to org.mozilla.javascript
in your java class file.
// import sun.org.mozilla.javascript.internal.NativeObject; // <=== Do not use this package.import org.mozilla.javascript.NativeObject;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
And everything works fine.
Post a Comment for "Java 7 + Rhino 1.7r3 Support For Commonjs Modules?"