FULL PRODUCT VERSION :
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
We have a Swing-Application which we are trying to enhance with some JavaFX-Webviews to display Webpages. We need to communicate between Swing and the Webpage. We are using JavaScript to send data from Swing to the Webpage. This works fine as long we are only using one Webpage. Once we add a second Webpage we get error messages like this one "ReferenceError: Can't find variable: changeHtml".
We are using a ChangeListener on the LoadWorker of a WebEngine to find out once if a page is loaded completely. But this does not work because for our failing webpages the states are
READ -> SUCCEEDED (the JavaScript files are not loaded here)
SUCCEEDED -> SCHEDULED
SCHEDULED -> RUNNING (this is where the page is actually loaded completely)
I was able to reproduce this with only JavaFX when using Platform.runLater to add multiple webpages. When not using Platform.runLater it works.
We are using Platform.runLater in Swing because we are adding webviews to different tabs.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
- Create an application.
- Add two WebViews with Platform.runLater
- Add a ChangeListener to each LoadWorker
- Execute JavaScript in an external js-File of the HTML-Page when the new-state is SUCCEEDED
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The JavaScript should be executed. In the sample application below both WebPages should change it's text and change it;s color.
ACTUAL -
ReferenceError: Can't find variable: XYZ
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "JavaFX Application Thread" netscape.javascript.JSException: ReferenceError: Can't find variable: changeHtml
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:1427)
at javafx.scene.web.WebEngine.executeScript(WebEngine.java:948)
at javafxbug.MyApplication$3.changed(MyApplication.java:57)
at javafxbug.MyApplication$3.changed(MyApplication.java:1)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.ReadOnlyObjectWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyObjectWrapper.java:176)
at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:142)
at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146)
at javafx.scene.web.WebEngine$LoadWorker.updateState(WebEngine.java:1226)
at javafx.scene.web.WebEngine$LoadWorker.dispatchLoadEvent(WebEngine.java:1337)
at javafx.scene.web.WebEngine$LoadWorker.access$1100(WebEngine.java:1219)
at javafx.scene.web.WebEngine$PageLoadListener.dispatchLoadEvent(WebEngine.java:1206)
at com.sun.webkit.WebPage.fireLoadEvent(WebPage.java:2388)
at com.sun.webkit.WebPage.fwkFireLoadEvent(WebPage.java:2232)
at com.sun.webkit.network.URLLoader.twkDidFinishLoading(Native Method)
at com.sun.webkit.network.URLLoader.notifyDidFinishLoading(URLLoader.java:830)
at com.sun.webkit.network.URLLoader.lambda$didFinishLoading$95(URLLoader.java:821)
at com.sun.webkit.network.URLLoader$$Lambda$117/1700372441.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$170(PlatformImpl.java:295)
at com.sun.javafx.application.PlatformImpl$$Lambda$48/349422632.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$171(PlatformImpl.java:294)
at com.sun.javafx.application.PlatformImpl$$Lambda$47/237061348.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$145(WinApplication.java:101)
at com.sun.glass.ui.win.WinApplication$$Lambda$36/2117255219.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
MyApplication.java
package javafxbug;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker.State;
import javafx.scene.Scene;
import javafx.scene.layout.FlowPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class MyApplication extends Application {
public static void main(String[] args) {
launch();
}
@Override
public void start(Stage stage) throws Exception {
FlowPane pane = new FlowPane();
Scene scene = new Scene(pane);
Platform.runLater(new Runnable() {
@Override
public void run() {
WebView webview1 = createWebview(getClass().getResource("/test.html").toExternalForm());
pane.getChildren().add(webview1);
}
});
Platform.runLater(new Runnable() {
@Override
public void run() {
WebView webview2 = createWebview(getClass().getResource("/test.html").toExternalForm());
pane.getChildren().add(webview2);
}
});
stage.setScene(scene);
stage.show();
}
private WebView createWebview(String url) {
WebView webview = new WebView();
final WebEngine webEngine = webview.getEngine();
webEngine.load(url);
webview.setPrefHeight(300);
webview.setPrefWidth(5300);
webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
@Override
public void changed(ObservableValue<? extends State> arg0, State arg1, State arg2) {
System.out.println("OldValue " + arg1 + " , Newvalue " + arg2);
if (arg2.equals(State.SUCCEEDED))
webEngine.executeScript("changeHtml();");
}
});
return webview;
}
}
-------
test.html
<html>
<body>
<script type="text/javascript" src="test.js"></script>
<div id="test" style="background-color: red;">Before javascript</div>
</body>
</html>
-------
test.js
function changeHtml() {
var divToBeChanged = document.getElementById('test');
divToBeChanged.innerHTML='After Javascript';
divToBeChanged.style.backgroundColor='green';
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Run the JavaScript function if the state is SUCCEEDED or the State is RUNNING. Catch exceptions if the JavaScript-Name is not known.
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
A DESCRIPTION OF THE PROBLEM :
We have a Swing-Application which we are trying to enhance with some JavaFX-Webviews to display Webpages. We need to communicate between Swing and the Webpage. We are using JavaScript to send data from Swing to the Webpage. This works fine as long we are only using one Webpage. Once we add a second Webpage we get error messages like this one "ReferenceError: Can't find variable: changeHtml".
We are using a ChangeListener on the LoadWorker of a WebEngine to find out once if a page is loaded completely. But this does not work because for our failing webpages the states are
READ -> SUCCEEDED (the JavaScript files are not loaded here)
SUCCEEDED -> SCHEDULED
SCHEDULED -> RUNNING (this is where the page is actually loaded completely)
I was able to reproduce this with only JavaFX when using Platform.runLater to add multiple webpages. When not using Platform.runLater it works.
We are using Platform.runLater in Swing because we are adding webviews to different tabs.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
- Create an application.
- Add two WebViews with Platform.runLater
- Add a ChangeListener to each LoadWorker
- Execute JavaScript in an external js-File of the HTML-Page when the new-state is SUCCEEDED
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The JavaScript should be executed. In the sample application below both WebPages should change it's text and change it;s color.
ACTUAL -
ReferenceError: Can't find variable: XYZ
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "JavaFX Application Thread" netscape.javascript.JSException: ReferenceError: Can't find variable: changeHtml
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:1427)
at javafx.scene.web.WebEngine.executeScript(WebEngine.java:948)
at javafxbug.MyApplication$3.changed(MyApplication.java:57)
at javafxbug.MyApplication$3.changed(MyApplication.java:1)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.ReadOnlyObjectWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(ReadOnlyObjectWrapper.java:176)
at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:142)
at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146)
at javafx.scene.web.WebEngine$LoadWorker.updateState(WebEngine.java:1226)
at javafx.scene.web.WebEngine$LoadWorker.dispatchLoadEvent(WebEngine.java:1337)
at javafx.scene.web.WebEngine$LoadWorker.access$1100(WebEngine.java:1219)
at javafx.scene.web.WebEngine$PageLoadListener.dispatchLoadEvent(WebEngine.java:1206)
at com.sun.webkit.WebPage.fireLoadEvent(WebPage.java:2388)
at com.sun.webkit.WebPage.fwkFireLoadEvent(WebPage.java:2232)
at com.sun.webkit.network.URLLoader.twkDidFinishLoading(Native Method)
at com.sun.webkit.network.URLLoader.notifyDidFinishLoading(URLLoader.java:830)
at com.sun.webkit.network.URLLoader.lambda$didFinishLoading$95(URLLoader.java:821)
at com.sun.webkit.network.URLLoader$$Lambda$117/1700372441.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$170(PlatformImpl.java:295)
at com.sun.javafx.application.PlatformImpl$$Lambda$48/349422632.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$171(PlatformImpl.java:294)
at com.sun.javafx.application.PlatformImpl$$Lambda$47/237061348.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$145(WinApplication.java:101)
at com.sun.glass.ui.win.WinApplication$$Lambda$36/2117255219.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
MyApplication.java
package javafxbug;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker.State;
import javafx.scene.Scene;
import javafx.scene.layout.FlowPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class MyApplication extends Application {
public static void main(String[] args) {
launch();
}
@Override
public void start(Stage stage) throws Exception {
FlowPane pane = new FlowPane();
Scene scene = new Scene(pane);
Platform.runLater(new Runnable() {
@Override
public void run() {
WebView webview1 = createWebview(getClass().getResource("/test.html").toExternalForm());
pane.getChildren().add(webview1);
}
});
Platform.runLater(new Runnable() {
@Override
public void run() {
WebView webview2 = createWebview(getClass().getResource("/test.html").toExternalForm());
pane.getChildren().add(webview2);
}
});
stage.setScene(scene);
stage.show();
}
private WebView createWebview(String url) {
WebView webview = new WebView();
final WebEngine webEngine = webview.getEngine();
webEngine.load(url);
webview.setPrefHeight(300);
webview.setPrefWidth(5300);
webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
@Override
public void changed(ObservableValue<? extends State> arg0, State arg1, State arg2) {
System.out.println("OldValue " + arg1 + " , Newvalue " + arg2);
if (arg2.equals(State.SUCCEEDED))
webEngine.executeScript("changeHtml();");
}
});
return webview;
}
}
-------
test.html
<html>
<body>
<script type="text/javascript" src="test.js"></script>
<div id="test" style="background-color: red;">Before javascript</div>
</body>
</html>
-------
test.js
function changeHtml() {
var divToBeChanged = document.getElementById('test');
divToBeChanged.innerHTML='After Javascript';
divToBeChanged.style.backgroundColor='green';
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Run the JavaScript function if the state is SUCCEEDED or the State is RUNNING. Catch exceptions if the JavaScript-Name is not known.