While experimenting JavaFX + HTML5/JS, and I've come across AMD modules (RequireJS).
I know how to inject Java objects and use them within the "old-fashioned" Javascript (everything in the global scope), but I'm now wondering how I to inject a Java object in a RequireJS module.
Any advice?
As I feel that I didn't make myself clear enough, let me be more specific.
My goal is to display my Javascript logs both on the browser console and the Java console because I don't want to include firebug-lite.j. To do that (in a simplified way):
.
public class DummyLogger {
void log(String msg) {
System.out.println("LOG (JS) : " + msg);
}
}
.
WebView webView = new WebView()
webView.getEngine().load("index.html");
// Inject our Java logger interface to JS
final JSObject jsWnd = (JSObject) webView.getEngine().executeScript("window");
jsWnd.setMember("javaLogger", logger);
.
define(function() {
return {
log: function(message) {
console.log(message);
// Forward to the injected Java logger only if it is defined
if(typeof javaLogger !== 'undefined') {
javaLogger.log(message);
}
}
}
}
Now, I'm wondering whether or not it is possible to inject the javaLogger object to the logger module without polluting the window namespace (which is kindda the point of AMD...).
My idea was to do something like:
.
WebView webView = new WebView()
WebEngine engine = webView.getEngine();
engine.getLoadWorker().stateProperty().addListener(
(observable, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
final JSObject retVal = (JSObject) engine.executeScript(
"require(['module/logger'], function(logger) { return logger; });"
);
retVal.call("setJavaLogger", logger);
}
}
);
engine.load("index.html");
Unfortunately, this does nothing. Does the require function return something?
Is it even possible to retrieve my logger module in Java?
From Java, it is possible to access a RequireJS module with something like:
WebView webView = new WebView();
WebEngine engine = webView.getEngine();
engine.load("path/to/index.html");
// Assuming that somewhere in 'index.html', the loading of "module/logger" is triggered...
{ ... let some time pass ...} //
final JSObject loggerModule = (JSObject) engine.executeScript(
"require('module/logger')"
);
logger.call("trace", "hello world!");
WARNING: The loading of both the HTML page and the RequireJS modules are asynchronous!
The execution of require(String)
might fail and throw a netscape.javascript.JSException
because the 'module/logger'
is not yet loaded. Such exception shall look like:
netscape.javascript.JSException: Error: Module name "module/logger" has not been loaded yet for context: _. Use require([])
http://requirejs.org/docs/errors.html#notloaded
at com.sun.webkit.dom.JSObject.fwkMakeException(JSObject.java:128)
at com.sun.webkit.WebPage.twkExecuteScript(Native Method)
at com.sun.webkit.WebPage.executeScript(WebPage.java:1426)
at javafx.scene.web.WebEngine.executeScript(WebEngine.java:948)
many more...
You will have to find a more or less creative way to wait until your module is loaded.