import org.w3c.dom.NodeList;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class JavaFxNpe extends Application {
    private final EventListener listener = this::onButtonClicked;
    private WebView webView;

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("NPE on WebView event");

        Pane root = new VBox();

        webView = new WebView();
        final Button button = new Button("Open Page");

        button.setOnAction(event -> loadWebPage());
        root.getChildren().add(button);
        root.getChildren().add(webView);

        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();

        webView.getEngine().getLoadWorker().stateProperty().addListener(this::onStateChanged);
    }

    private void loadWebPage() {
		webView.getEngine().loadContent(
				" <!DOCTYPE html><html lang=\"en\"><head><meta charset=\"utf-8\"><title>Submit Test</title></head><body><button>Close Page</button></body></html> ");
    }

    private void onStateChanged(ObservableValue<? extends Worker.State> observable,
                                Worker.State oldState,
                                Worker.State newState) {
        if (newState != Worker.State.SUCCEEDED) {
            return;
        }

        final NodeList nodeList = webView.getEngine().getDocument().getElementsByTagName("button");
        for (int i = 0; i < nodeList.getLength(); i++) {
            final EventTarget eventTarget = (EventTarget) nodeList.item(i);
            eventTarget.addEventListener("click", this.listener, true);
        }
    }

    private void onButtonClicked(Event event) {
        // On JFX thead
        webView.getEngine().load("about:blank");
        // Need to delay the GC to after this event is handled, but we also want a GC before we open
        // the page again.
        Platform.runLater(System::gc);
    }
} 