Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a Java method from a JavaFX webview

In my project I have an HTML document that is displayed in a JavaFx WebView. I have a Javascript function that should call the Java method getData (currently it only prints the passed variable so that I can confirm the data is being passed from the WebView back to the Java application):

    public void getData(String s){
        System.out.println(s);
    }

This is how I am attempting to add the functionality to call Java methods into my WebView webpage:

    JSObject win = (JSObject) webEngine.getDocument();
    win.setMember("app", new Bridge());

And here is the JavaScript function that I'm using to call getData:

     function interOp(val){
        app.getData(val);
     }

This function is called on the onchange event on a <select> tag. The guides I have followed seem to do exactly this, however when I run my program nothing is printed on the console.

like image 898
TomRaikes Avatar asked Nov 01 '25 05:11

TomRaikes


2 Answers

I have found a resolution for this issue: instead of using webEngine.getDocument();, which returns an HTMLdocument object, use webEngine.executeScript("window"); which gives a window object.

like image 156
TomRaikes Avatar answered Nov 03 '25 19:11

TomRaikes


My solution was to create the object before passing it... so this:

JSObject win = (JSObject) webEngine.getDocument();
win.setMember("app", new Bridge());"

becomes this:

Bridge bridgeREF = new Bridge();
JSObject win = (JSObject) webEngine.getDocument();
win.setMember("app", bridgeREF);

This came from a bug report I read here: https://bugs.openjdk.java.net/browse/JDK-8170515

Otherwise, the javascript call seemed to work half the time... needed a refresh sometimes. It was really odd.

Though my code is/was a little different... here's how I register the java class "JavaApp" with the JavaFX window:

        Platform.runLater(new Runnable() {
        @Override
        public void run() {

  JavaApp appREF = new JavaApp(webEngine); 
  webEngine.getLoadWorker().stateProperty().addListener(
        new ChangeListener<State>() {
          @Override public void changed(ObservableValue ov, State oldState, State newState) {

              if (newState == Worker.State.SUCCEEDED) {

                  JSObject win = (JSObject) webEngine.executeScript("window");
                    win.setMember("app", appREF);  
            }

            }
        });
   //other code for loading html, listeners, etc...
   }

The reference to the class should be created outside of the anonymous listener, else the garbage collector might get it. Which is what (I think) was causing the erratic behavior I was experiencing... your java class may or may not need the reference to webEngine.. I use that for loading another url after sending a file.

I don't think it matters whether you use Window or Document... except that window might be more persistent depending on whether you use full page loads or not.

like image 32
pcalkins Avatar answered Nov 03 '25 20:11

pcalkins