JavaFX WebView does not load page

2.9k Views Asked by At

I am trying to open "engine.load("https://login.microsoftonline.com");" in JavaFX WebView.

When using jdk1.8.0_161 the page is loaded. When using jdk1.8.0_181 the page does not load. It displays empty window and does not return any error: engine.getLoadWorker().exceptionProperty() is null.

Do you have any idea what might have changed in new version updates of Java? I tested on Java 10 latest release and the page is also not loaded. This code works with JDK8.161 and JDK9.0.4 but does not work with JDK8.181 and JDK10.0.2

Here is the source code of the sample app I have created:

import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker.State;
import javafx.embed.swing.JFXPanel;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebErrorEvent;
import javafx.scene.web.WebEvent;
import javafx.scene.web.WebView;
import javafx.util.Callback;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.swing.*;

import org.w3c.dom.Document;

public class LoginApplicationWindow {

    public static void main(String args[]) {
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(620, 440);
        final JFXPanel fxpanel = new JFXPanel();
        frame.add(fxpanel);

        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                WebEngine engine;               
                WebView wv = new WebView();
                engine = wv.getEngine();
                engine.setJavaScriptEnabled(true);

                 // Create a trust manager that does not validate certificate chains
                TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {

                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        // TODO Auto-generated method stub
                        return null;
                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        // TODO Auto-generated method stub

                    }

                    @Override
                    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        // TODO Auto-generated method stub

                    }
                }};

                // Install the all-trusting trust manager
                SSLContext sc;
                try {
                    sc = SSLContext.getInstance("SSL");
                    sc.init(null, trustAllCerts, new java.security.SecureRandom());
                    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
                } catch (NoSuchAlgorithmException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (KeyManagementException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }


                // Create all-trusting host name verifier
                HostnameVerifier allHostsValid = new HostnameVerifier() {

                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        // TODO Auto-generated method stub
                        return true;
                    }
                };

                // Install the all-trusting host verifier
                HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);

                engine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
                      public void changed(ObservableValue ov, State oldState, State newState) {
                        if (newState == State.SUCCEEDED) {
                          Document doc = engine.getDocument();
                          // operations on dom occur here.
                          System.out.println(engine.getLoadWorker().exceptionProperty());
                          System.out.print("load finished " + doc.getBaseURI());
                        }
                      }
                });


                engine.setOnAlert(new EventHandler<WebEvent<String>>() {

                    @Override
                    public void handle(WebEvent<String> event) {
                        System.out.print("setOnAlert " + event.getData());
                    }
                });

                engine.setOnError(new EventHandler<WebErrorEvent>() {

                    @Override
                    public void handle(WebErrorEvent event) {
                        System.out.print("onError " + event.getMessage());
                    }
                });

                engine.setConfirmHandler(new Callback<String, Boolean>() {

                    @Override
                    public Boolean call(String param) {
                        // TODO Auto-generated method stub
                        System.out.print("setConfirmHandler " + param);
                        return null;
                    }
                });


                fxpanel.setScene(new Scene(wv));
                engine.load("https://login.microsoftonline.com");
                //engine.load("https://facebook.com");

            }
        });
        frame.setVisible(true);
    }
}

enter image description here

1

There are 1 best solutions below

2
On

It turned out that ANY network problem (DNS/connection) can cause the error and the load will not throw any proper exception. The good news is that if you replace the .load(url) call, at least you will see the problems in the log.

On replacing I mean that load the site separately to a String

private static String getData(String address) throws Exception {
    URL page = new URL(address);
    StringBuffer text = new StringBuffer();
    HttpURLConnection conn = (HttpURLConnection) page.openConnection();
    conn.connect();
    try (InputStreamReader in = new InputStreamReader(
            (InputStream) conn.getContent())) {
        BufferedReader buff = new BufferedReader(in);
        String line;
        do {
            line = buff.readLine();
            text.append(line + "\n");
        } while (line != null);
        return text.toString();
    } finally {
        conn.disconnect();
    }
}

And replace the .load:

    //engine.load("https://login.microsoftonline.com");
    engine.loadContent(getData("https://login.microsoftonline.com"));

Of course, the exception should be catched and logged properly. (The funny thing is that the referenced resources (images/js/css whatever files) will be loaded well in this way too.)