Dojo supports Mozilla's Rhino engine for things like headless DOH tests and builds. This post demonstrates how to bootstrap Dojo using an embedded context.
This information pertains to Dojo 1.7.2, Rhino 1.7R2 and Java 6. Knowledge of JavaScript, Dojo and Java is assumed.
Dojo in the Rhino shell
The command
java -cp js.jar org.mozilla.javascript.tools.shell.Main ./dojo/dojo/dojo.js baseUrl=./dojo/dojo load=doh
results in the output:
------------------------------------------------------------ The Dojo Unit Test Harness, $Rev: 23869 $ Copyright (c) 2011, The Dojo Foundation, All Rights Reserved ------------------------------------------------------------ 0 tests to run in 0 groups ------------------------------------------------------------ | TEST SUMMARY: ------------------------------------------------------------ 0 tests in 0 groups 0 errors 0 failures
This isn't particularly useful but it demonstrates that Dojo loaded without error.
Embedded Rhino
Embedding Rhino in a Java application gives you more programmatic control over JavaScript execution than would be the case if you just relied on the shell.
A trivial Rhino application:
import org.mozilla.javascript.*; public class HelloEmbedded { public static void main(String[] args) { String source = "java.lang.System.out.println('Hello, Rhino!');"; Context context = new ContextFactory().enterContext(); ScriptableObject scope = context.initStandardObjects(); context.evaluateString(scope, source, "<cmd>", 1, null); } }
This code initializes the Rhino engine and uses JavaScript to print a string to STDOUT.
Embedded Dojo
Simply trying to load Dojo won't work:
// don't use public class BrokenBootstrap { public static void main(String[] args) throws IOException { String baseUrl = "./dojo/dojo"; String dojo = baseUrl + "/dojo.js"; Object[] dojoArgs = { "baseUrl=" + baseUrl, "load=doh" }; ContextFactory factory = new ContextFactory(); Context context = factory.enterContext(); ScriptableObject scope = context.initStandardObjects(); Scriptable arguments = context.newArray(scope, dojoArgs); scope.defineProperty("arguments", arguments, ScriptableObject.DONTENUM); Reader reader = new FileReader(dojo); try { context.evaluateReader(scope, reader, dojo, 1, null); } finally { reader.close(); } } }
Rhino throws the exception
Exception in thread "main" org.mozilla.javascript.EcmaError: ReferenceError: "location" is not defined. (./dojo/dojo/dojo.js#237)
.
This is because Dojo attempts to use browser features because it has failed to detect that it is running in Rhino.
Dojo relies on features provided by the shell that are not present in an embedded context to detect the environment
and load and execute modules.
The simplest way round this is to reuse the Global
type that provides these features to the shell:
import java.io.*; import org.mozilla.javascript.*; import org.mozilla.javascript.tools.shell.Global; public class Bootstrap { public static void main(String[] args) throws IOException { String baseUrl = "./dojo/dojo"; String dojo = baseUrl + "/dojo.js"; Object[] dojoArgs = { "baseUrl=" + baseUrl, "load=doh" }; ContextFactory factory = new ContextFactory(); Context context = factory.enterContext(); Global global = new Global(); global.init(context); Scriptable arguments = context.newArray(global, dojoArgs); global.defineProperty("arguments", arguments, ScriptableObject.DONTENUM); Reader reader = new FileReader(dojo); try { context.evaluateReader(global, reader, dojo, 1, null); } finally { reader.close(); } } }
This gives us the same DOH bootstrap message from the shell command. There is likely a bit more work involved if you want to do something useful.
No comments:
Post a Comment
All comments are moderated