Handshake failure when loading images from external url on JLink build

348 views Asked by At

Solved - See my answer

Problem

I'm trying to load images from external URLs and set them to an ImageView using JavaFX. It always works when running inside the IDE, but when I build the project using JLink, only images from a few URLs work.

Error

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
        at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
        at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
        at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:313)
        at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293)
        at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:186)
        at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164)
        at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1144)
        at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1055)
        at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:395)
        at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:567)
        at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
        at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1587)
        at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1515)
        at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:250)

Code

Initially, I thought the problem was that I was not setting a User-Agent, so I modified my code to the following:

public boolean loadImage() {

        if (!imageURL.isBlank() && image == null) {

            try {

                URLConnection conn = new URL(imageURL).openConnection();
                conn.setRequestProperty("User-Agent", "Wget/1.13.4 (linux-gnu)");
                InputStream stream = conn.getInputStream();
                this.image = new Image(stream);

                //original code
                //this.image = new Image(imageURL, true); 

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        return image != null && image.isError();
    }

In a few sites, https://imgur.com for instance, it works, even with the older code this.image = new Image(imageURL, true);. But on the majority of the sites I tried I received the same error: handshake_failure.

Even after changing the code, the error continued. I tried searching but only found answers related to databases.

Project

You may test yourself cloning the project from its repository. You will need to update the loadImage function on this file (Project.java:99) to the example above since the one hosted on GitHub is the older version.

If you run it on the IDE, using gradlew run, it will work as expected. To check if the images are loading, go to Projects > Use Sample Data on the menu bar. Once the sample data is displayed, double-click any of the products, and the image should display on the right side. All the sample products have images; if it's not working you will see a label "This product has no image".

The moment you run it from the JLink generated image at /build/image/bin/StockManager.bat, you will get the handshake_failure error. From the products available in the sample data, the only one that is working is the "Gaming Laptop".

As of right now, the "workaround" I'm using is to host all images in https://imgur.com since this error doesn't happen when the image is hosted there.

1

There are 1 answers

0
Picoral On BEST ANSWER

Solution

It turns out I needed to include requires jdk.crypto.ec; on my module-info.java. After adding it, it worked properly both in the IDE and in the JLink build.

This question helped me to find this solution