Html/Javascript debugging in JavaFX WebView
Here is some Java code to make use of Firebug Lite in a JavaFX WebView without modifying the html of the target page.
webView.getEngine().executeScript("if (!document.getElementById('FirebugLite')){E = document['createElement' + 'NS'] && document.documentElement.namespaceURI;E = E ? document['createElement' + 'NS'](E, 'script') : document['createElement']('script');E['setAttribute']('id', 'FirebugLite');E['setAttribute']('src', 'https://getfirebug.com/' + 'firebug-lite.js' + '#startOpened');E['setAttribute']('FirebugLite', '4');(document['getElementsByTagName']('head')[0] || document['getElementsByTagName']('body')[0]).appendChild(E);E = new Image;E['setAttribute']('src', 'https://getfirebug.com/' + '#startOpened');}");
You can trigger the code using a JavaFX Button or any other mechanism you wish.
JAVAFX / WebView / WebEngine FireBugLite or Some other debugger?
I was able to fix the problem. It seems like the current stable version of FirebugLite works well for traditional browsers but something is different that makes it fail for an application viewed by the JAVAFX WebView.
I was able to add Firebug to my application by using an uncompressed version of FirebugLite
<script type='text/javascript' src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
The solution came from: Testing IE6 with Firebug Lite
JavaFx WebView callback from Javascript failing after Garbage Collection
I solved the problem by creating an instance variable bridge
in Java that holds the JavaScriptBridge
instance sent to Javascript via setMember()
. This way, Gargbage Collection of the instance is prevented.
Relevant code snippet:
public class JavaScriptBridge {
public void callback(String data) {
System.out.println("callback retrieved: " + data);
}
}
private JavaScriptBridge bridge;
@Override
public void start(Stage primaryStage) throws Exception {
WebView webView = new WebView();
primaryStage.setScene(new Scene(new AnchorPane(webView)));
primaryStage.show();
final WebEngine webEngine = webView.getEngine();
webEngine.load(getClass().getClassLoader().getResource("page.html").toExternalForm());
bridge = new JavaScriptBridge();
webEngine.getLoadWorker().stateProperty().addListener((observableValue, oldValue, newValue) -> {
if (newValue == State.SUCCEEDED) {
JSObject window = (JSObject) webEngine.executeScript("window");
window.setMember("javaApp", bridge);
}
});
webEngine.setOnAlert(event -> {
System.out.println(DATE_FORMAT.format(new Date()) + " alerted: " + event.getData());
});
}
Altough the code now works smoothly (also in conjunction with Leaflet), I am still irritated of this unexpected behaviour...
Edit: The explanation for this behaviour is documented since Java 9 (thanks @dsh for your clarifying comment! I was working with Java 8 at the time and unfortunately didn't have this information at hand...)
javafx webview does not display correctly an html page
Background on Test Environment
I ran some experimentations to determine what is causing (at least some of) your reported issues with the display of your provuded page.
For my tests I was using JavaFX 17.0.0.1 running Eclipse Temurin 17 JDK and Windows 10 Pro OS on MS Surface Book 2.
The sample webpage from your question displayed in Chrome 94 without the issues you note in your question, and in JavaFX WebView experienced the issues you note in your question.
To debug the issue, I added a console listener to the web engine, as demonstrated in the most popular answers to:
- How to get the JavaFx WebEngine to report errors in detail?
- WebConsoleListener IllegalAccessError in JavaFX 12
Once I did so, I saw the following error logged to the console:
Console: [https://cdn.jsdelivr.net/npm/chart.js:13] ReferenceError: Can't find variable: ResizeObserver
Information on ResizeObserver
Doing some research I could see that the ResizeObserver implementation isn't available for all browser implementations. So I guess it isn't implemented in WebView.
Information on ResizeObserver from Mozilla
- https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver
Sample test page for ResizeObserver from Mozilla (I am not responsible for the weird text message in the sample):
- https://mdn.github.io/dom-examples/resize-observer/resize-observer-text.html
Loading the sample page from mozilla in WebView confirms the issue with lack of support for ResizeObserver, with the following error printed when the WebConsoleListener is attached:
Console: [https://mdn.github.io/dom-examples/resize-observer/resize-observer-text.html:110] Resize observer not supported!
How to fix it
You can add the ResizeObserver ability to WebView (or other browsers which do not support the feature) via a polyfill.
The best way to fix it is to request the developers of the website you are using to integrate a polyfill for ResizeObserver into their website to allow it to be used on a wider variety of clients.
An example polyfill which fixes the issue is:
- ResizeObserver polyfill.
If you download the source for the website you are using and import the polyfill JavaScript in the page before other items, then, most of the issues you reference in your question go away and work as expected on WebView:
- No error is displayed in the console regarding the ResizeObserver.
- The display automatically changes every 10 seconds.
- Graphs display when you click on the second circle.
- An image displays when you click on the third circle (though the image is larger than what I see on Chrome and clipped).
Polyfill javascript source for ResizeObserver:
- https://github.com/que-etc/resize-observer-polyfill/blob/master/dist/ResizeObserver.js
Filing a feature request for ResizeObserver support for JavaFX WebView
If you wish, you can file a feature request for the JavaFX WebView requesting resize observer support.
To do so, you could subscribe to the openjfx-dev mailing list and post a message about this there, linking back to this question.
Or, file a bug report against JavaFX. If you do so, I'd advise referencing the mozilla resize observer test page and associated documentation rather than the test page in your original question.
Test Code
Must be run using the information from: this answer to allow access to an internal com.sun.javafx
implementation.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.web.WebEngine;
import javafx.stage.Stage;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebView;
import com.sun.javafx.webkit.WebConsoleListener;
public class WebViewPageLoad extends Application {
@Override
public void start(final Stage stage) {
WebView webView = new WebView();
WebEngine engine = webView.getEngine();
engine.getLoadWorker().exceptionProperty().addListener((ov, t, t1) ->
System.out.println("Received exception: "+t1.getMessage())
);
WebConsoleListener.setDefaultListener((webViewReference, message, lineNumber, sourceId) ->
System.out.println("Console: [" + sourceId + ":" + lineNumber + "] " + message)
);
// test page from original question:
engine.load("http://it-topics.com/index3.html");
// test page for resize observer polyfill (functions as expected).
// engine.load("https://que-etc.github.io/resize-observer-polyfill/");
// canonical ResizeObserver test page from mozilla.
// engine.load("https://mdn.github.io/dom-examples/resize-observer/resize-observer-text.html");
// referencing a local hacked version of the it-topics.com index3.html.
// engine.load(WebViewPageLoad.class.getResource("it.html").toExternalForm());
VBox layout = new VBox(webView);
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) {
launch();
}
}
Related Topics
Click Is Not Working on the Listitem Listview Android
Eclipse: Jvm Terminated. Exit Code=2
Why Menuitemcompat.Getactionprovider Returns Null
How to Remove a Specific Element from a JSONarray
Android Color Notification Icon
How to Remove Only Trailing Spaces of a String in Java and Keep Leading Spaces
Android Httpclient Persistent Cookies
How to Change Method Behaviour Through Reflection
Caused By: Java.Lang.Classnotfoundexception: Didn't Find Class in Firebase Phone Authentication
Why Do We Have to Call Super in Android Sometimes
Android (Java) Simple Send and Receive with Server - Fast Setup Challenge
Change Name of Import in Java, or Import Two Classes with the Same Name
How to Find Gcd, Lcm on a Set of Numbers