Search code examples
javajlinkjpackage

HttpClient .send() throws IOException when running outside the IDE


I try to get the latest release tag of a Github repositiory via HttpClient.
The plan is to send a request to github.com/user/repository/releases/latest and get the uri of the redirect to determine the latest release tag.

When the program is running in my IDE, everything works fine. But for some reasons a IOException is thrown when the program is jlinked + jpackaged.
I allready tried to run it as an admin to rule that out.

My code:

  private static String latestVersionTag() {
        HttpClient client = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.NORMAL).build();
        HttpRequest request = HttpRequest
                .newBuilder(URI.create("https://github.com/{placeholderUser}/{placeholderRepo}/releases/latest"))
                .timeout(Duration.ofSeconds(5))
                .build();

        try {
            HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
            String path = response.uri().getPath();
            return path.substring(path.lastIndexOf('/') + 1);
        } catch (IOException | InterruptedException e) {
            return null;
        }
    }

Edit: i ran the jlinked image without packaging to get the stack trace (haven't thought of that before, sorry)

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
        at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:576)
        at java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:123)
        at launchofexile/com.github.cptblacksheep.launchofexile.UpdateChecker.latestVersionTag(UpdateChecker.java:76)
        at launchofexile/com.github.cptblacksheep.launchofexile.UpdateChecker.checkForNewVersion(UpdateChecker.java:35)
        at launchofexile/com.github.cptblacksheep.launchofexile.UpdateChecker.startupCheckForNewVersion(UpdateChecker.java:28)
        at launchofexile/com.github.cptblacksheep.launchofexile.LaunchOfExileMain.initialize(LaunchOfExileMain.java:285)
        at launchofexile/com.github.cptblacksheep.launchofexile.LaunchOfExileMain.main(LaunchOfExileMain.java:475)
Caused by: 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:358)
        at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293)
        at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:204)
        at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172)
        at java.base/sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:736)
        at java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:691)
        at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:506)
        at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:482)
        at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:679)
        at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader.unwrapBuffer(SSLFlowDelegate.java:529)
        at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader.processData(SSLFlowDelegate.java:433)
        at java.net.http/jdk.internal.net.http.common.SSLFlowDelegate$Reader$ReaderDownstreamPusher.run(SSLFlowDelegate.java:268)
        at java.net.http/jdk.internal.net.http.common.SequentialScheduler$LockingRestartableTask.run(SequentialScheduler.java:205)
        at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:149)
        at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:230)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
        at java.base/java.lang.Thread.run(Thread.java:833)

Solution

  • The handshake is failing because your custom run-time image is missing the necessary cryptography modules. Adding:

    --add-modules jdk.crypto.cryptoki,jdk.crypto.ec
    

    When running jlink should fix the problem.

    I'm not sure if you absolutely need both modules, or which of the two is the necessary one if you don't need both. It's also possible one of them requires the other, causing the other to be implicitly pulled in.