I'm making a web based app with Java support for some particular requests (e.g. print without choosing the printer everytime) and there is something that id driving me crazy.
I use JavaFX for instantiate the browser object and everything works fine, but of course I need to make callbacks from JavaScript to Java, here is the code:
...
...
we.getLoadWorker().stateProperty().addListener( new ChangeListener<Worker.State>()
{
@Override
public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue)
{
if ( newValue == Worker.State.SUCCEEDED )
{
bridge = new Bridge();
JSObject jsobj = (JSObject) we.executeScript( "window" );
jsobj.setMember( "app", new Bridge() );
}
if ( newValue == Worker.State.CANCELLED )
{
System.out.println( newValue );
System.out.println( "An error accourred" );
}
}
});
...
...
This works but after a few minutesthe bridge stoo working totally, javascript can't make callbacks anymore and if I try to make an alert() on the "app" object it return me undefined. I'm using JDK9
To make the solution more obvious: the approach suggested by @sillyfly works.
Instead of creating a new Bridge
(or in my case Console
) instance for every state change, make a single instance and reassign it every time. Something along the following lines.
public class AppController {
public WebView webview;
@FXML
public void initialize() {
final Console console = new Console();
final WebEngine engine = webview.getEngine();
engine.setJavaScriptEnabled(true);
engine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
@Override
public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) {
final JSObject window = (JSObject) engine.executeScript("window");
window.setMember("console", console);
}
});
}
public class Console {
public void log(String text) {
System.out.println("[WebView console] " + text);
}
}
}
来源:https://stackoverflow.com/questions/46744432/javafx-jsobject-stop-working-after-a-few-minutes