I retrieve an object from Java to my JavaScript in WebView, and want to call methods on it. Doesn't work.
I have a JavaFX WebView, which displays an html page. This page includes JavaScript. I set a Java object as member variable on the "window", so that I can call methods on it from JavaScript, as per the documentation:
WebEngine engine = webView.getEngine();
JSObject window = (JSObject) webEngine.executeScript("window");
window.setMember("manager", new Manager());
That's what I find in all examples. Assume the Manager class has a method, "doSomething()", I can call that method, on my Manager Java object, from JavaScript:
<script>
function onclick() {
manager.doSomething();
}
</script>
This works just fine.
However, assume the doSomething() returns an object, e.g. a Todo which has a method "getDescription()", which just returns a string.
It should look like this:
<script>
function onclick() {
var todo = manager.doSomething();
var desc = todo.getDescription();
document.getElementById("description-label").innerHTML = desc;
}
</script>
But that doesn't work for me. I cannot execute "todo.getDescription()". The WebView never prints any errors anywhere, as far as I can tell, no matter what I break, so it's tough to figure out the problem.
As I understand the documentation here https://docs.oracle.com/javafx/2/api/javafx/scene/web/WebEngine.html
with this explanation:
... a JavaRuntimeObject is created. This is a JavaScript object that acts as a proxy for the Java object, in that accessing properties of the JavaRuntimeObject causes the Java field or method with the same name to be accessed
My approach should work.
Eventually I just want to retrieve a collection of objects, and display their data in a table.
What am I doing wrong?
Calling Java from JavaScript
The example:
Labeland aWebView.JSObjectwith the JavaFX app.Some things to note:
Use current documentation on
WebEngine(for JavaFX 19), don't use outdated documentation from JavaFX 2.WebEnginewithin a modular environment. The additional information on modularity will be critical for some applications.To access the
WebView, use:To access the
JSObjectwhich bridges Java and the WebView, use:To have your code accessible to JavaScript executing in
WebView, use:This is required because, internally, the
WebEnginewill use reflection on your code to allow JavaScript to call it.Make sure the document is loaded before performing actions on it.
You don't (as far as I can tell) need to provide transitive access to the objects you return to the webview. For instance, in the JavaScript I call,
app.getLabel().getText();, but just opening the package with my app tojavafx.webis sufficient, I don't need to open thejavafx.scene.controlpackage tojavafx.web. I'm not exactly sure why things work like that, but that appeared to be the case.This JavaScript will also work:
But this next JavaScript will not work, because the type
Labelis not known to JavaScript, even though when you use thevarform you can execute methods on the var which is ajavafx.scene.control.Label:com/example/bridge/BridgeApp.java
module-info.java
pom.xml
Calling JavaScript from Java, passing data in the
executeScriptcallThe example in the answer is just for demo purposes, to demonstrate how to call Java code from a WebView. The same result could be accomplished by executing a script directly on the webengine as shown below, but then it wouldn't be demonstrating calling Java from JavaScript as requested in the question.