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.
Solution
It turns out I needed to include
requires jdk.crypto.ec;
on mymodule-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