2

I have a problem with displaying a webpage in an embedded window but only when creating a standalone jlinked package and only for certain https sites.

I followed the instructions at https://openjfx.io/openjfx-docs/#install-javafx for creating a simple modular App and this works fine when run from the command line with

java --module-path "%PATH_TO_FX%;mods" -m uk.co.comsci.testproj/uk.co.comsci.testproj.Launcher

but after jlinking with the command

jlink --module-path "%PATH_TO_FX_MODS%;mods" --add-modules uk.co.comsci.testproj --output launch

and running with

launch\bin\java.exe -m uk.co.comsci.testproj/uk.co.comsci.testproj.Launcher

the javaFx scene opens but just a blank screen... and I have to use task manager to terminate the App.

If I change the URL to other https sites, it displays fine.

I guess it is down to the security settings and policies somewhere but I have no idea where to start.

I have tried monitoring with WireShark and this shows that when run from java and it works it does some TLSv1.3 stuff to establish the connection. When run as a jlinked package it only does TLSv1.2 stuff. Maybe a clue?

Here's my SSCE:

module-info.java

module uk.co.comsci.testproj {
    requires javafx.web;
    requires javafx.controls;
    requires javafx.media;
    requires javafx.graphics;
    requires javafx.base;
    exports uk.co.comsci.testproj;
}

Launcher.java

package uk.co.comsci.testproj;

public class Launcher {
    public static void main(String[] args) {
        try {
            MainApp.main(args);
        } catch (Exception ex) {
            System.err.println("Exception!!! " + ex);
        }
    }
}

MainApp.java

package uk.co.comsci.testproj;

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class MainApp extends Application {

    private Stage mainStage;

    public static void main(String[] args) throws Exception {
        launch(args);
    }

    @Override
    public void start(final Stage initStage) throws Exception {

        mainStage = new Stage(StageStyle.DECORATED);

        mainStage.setTitle("Test Project");

        WebView browser = new WebView();
        WebEngine webEngine = browser.getEngine();

//        webEngine.load("https://app.comsci.co.uk"); // url);
        String uri = "https://test-api.service.hmrc.gov.uk/oauth/authorize"
                + "?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8084%2Fredirect"
                + "&state=lFuLG42uri_aAQ_bDBa9TZGGYD0BDKtFRv8xEaKbeQo"
                + "&client_id=tASN6IpBPt5OcIHlWzkaLXTAyMEa&scope=read%3Avat+write%3Avat";
        webEngine.load(uri);

        Button closeButt = new Button("Cancel");
        closeButt.setOnMouseClicked(event -> {
            mainStage.close();
        });
        HBox closeButBar = new HBox(closeButt);
        closeButBar.setAlignment(Pos.BASELINE_RIGHT);

        VBox vlo = new VBox(browser, closeButBar);
        vlo.setFillWidth(true);
        vlo.setSpacing(10.0);
        VBox.setVgrow(browser, Priority.ALWAYS);

        Scene scene2 = new Scene(vlo, 800, 800);
        mainStage.setScene(scene2);
        mainStage.initModality(Modality.APPLICATION_MODAL);
        mainStage.setTitle("Test connection");
        mainStage.showAndWait();
    }

}

Any help much appreciated.

2 Answers 2

6

OK. Finally tracked it down. So in case anyone has the same problem:

Nothing to do with JavaFx or Webview it was the TLS handshake failing.

Replacing the webview with an http client get

            String uri = "https://test-api.service.hmrc.gov.uk/oauth/authorize"
                    + "?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8084%2Fredirect"
                    + "&state=lFuLG42uri_aAQ_bDBa9TZGGYD0BDKtFRv8xEaKbeQo"
                    + "&client_id=tASN6IpBPt5OcIHlWzkaLXTAyMEa&scope=read%3Avat+write%3Avat";

            var client = HttpClient.newHttpClient();
            var request = HttpRequest.newBuilder()
                    .GET()
                    .uri(URI.create(uri))
                    .timeout(Duration.ofSeconds(15))
                    .build();

            try {
                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
                System.out.println("REsponse  " + response.body());
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }

and running with '-Djavax.net.debug=ssl:handshake:verbose' showed that the handshake was failing. running the embedded keytool -showinfo -tls and comparing this with the system keytool output showed that the TLS_ECDHE_... cyphers where not supported in the jlinked output

A bit of googling and help from here https://www.gubatron.com/blog/2019/04/25/solving-received-fatal-alert-handshake_failure-error-when-performing-https-connections-on-a-custom-made-jre-with-jlink/ showed that all I needed to do was add

requires jdk.crypto.cryptoki;

to my module-info.java :-)

Sign up to request clarification or add additional context in comments.

2 Comments

Great stuff! I was getting all kinds of odd behaviour from the WebView in my jlinked app (missing images/fonts/styles/etc) until I came across this answer!
Worked like a charm. The answer is really helpful. Was banging my head for couple of days in this issue. Thanks a lot @Comsci
0

You need to just add the following line in module-info.java

requires jdk.crypto.cryptoki;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.