5

I'm trying to run some SVG that contains Javascript in JavaFX's WebView. I know some of the scripts I'm trying to run have errors and am trying to figure out how to print them to the console so I can debug them. I've tried the following, but the WebErrorEvent is never called:

WebEngine webEngine = browser.getEngine();
webEngine.setOnError(new EventHandler<WebErrorEvent>()
{
    @Override
    public void handle(WebErrorEvent event)
    {
        System.err.println(event);
    }
});

Is this the right way to get javascript error feedback from this control?

kitfox
  • 4,534
  • 3
  • 17
  • 24

1 Answers1

1

setOnError listener only works for error while loading a given document.

One way to solve this is to call a Java method when console.log is called. You can do this by.

Your FX application

WebEngine engine = mainWebView.getEngine();
engine.load("http://whereever.com");

engine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
    @Override
    public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) {
        JSObject window = (JSObject) engine.executeScript("window");
        window.setMember("java", new Bridge());
        engine.executeScript("console.log = function(message) { java.log(message); }"); // Now where ever console.log is called in your html you will get a log in Java console
   }
});

Your Bridge class

public class Bridge {

    public void exit() {
        Platform.exit();
    }

    public void log(String text) {
        System.out.println(text);
    }

}

Your html

<h1>Text Page</h1>
<button onclick="java.log('This is log')">Log</button>
<button onclick="console.log('This produces the same result as above')">Console.log</button>
<button onclick="java.exit()">Exit</button>

Hope this is of some help.

Adi
  • 5,560
  • 1
  • 24
  • 37
  • To get the multiple parameters of `console.log` calls to be logged you can redefine console log like this `webEngine.executeScript("console.log = function() { java.log(Array.prototype.join.call(arguments, ' ')); }");`. Also, beware the `new Bridge()` object will get garbage collected and disappear on you, so you should assign it e.g. `private final Bridge bridge = new Bridge();` and then `window.setMember("java", bridge);`. Finally to `import netscape.javascript.JSObject;` in recent versions e.g. Java 20 you need to add `requires jdk.jsobject;` to your `src/main/java/module-info.java`. – abulka Jul 07 '23 at 06:10