I'm trying to connect to a WebSocket
from a WebView
in JavaFX (because I want to use a third-party component available only in Javascript). In the WebView
's HTML file, I used Javascript to create a WebSocket
instance, and in the JavaFX part, I used Java-WebSocket
to create a WebSocketServer
. But now, after the WebSocketServer
started and the Javascript WebSocket
client was initialized, the WebSocketServer
didn't seem to open a connection to the WebView
. What's more, if I open the HTML file in a browser (using IntelliJ IDEA's "open in browser" feature) while running the application, the WebSocket
seems to open a connection.
I have searched for some answers on Stack Overflow, but they all seem to be outdated.
Here is the code.
HelloApplication.java
package com.remmymilkyway.websocketdemo;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Objects;
public class HelloApplication extends Application {
private WebSocketServer server;
@Override
public void start(Stage stage) {
WebView webView = new WebView();
webView.getEngine().load(Objects.requireNonNull(this.getClass().getResource("web-view.html")).toExternalForm());
server = new WebSocketServer(new InetSocketAddress("localhost", 8080)) {
@Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
System.out.println("New connection: " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
}
@Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
System.out.println("Connection closed: " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
}
@Override
public void onMessage(WebSocket conn, String message) {
System.out.println("Received message: " + message);
}
@Override
public void onError(WebSocket conn, Exception ex) {
System.out.println("An error occurred: " + ex);
}
@Override
public void onStart() {
System.out.println("Server started");
}
};
server.start();
server.broadcast("Server started.");
Scene scene = new Scene(webView);
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
}
@Override
public void stop() throws Exception {
super.stop();
server.stop();
System.out.println("Server stopped");
}
public static void main(String[] args) {
launch();
}
}
web-view.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<p id="text"></p>
<script>
var webSocket = new WebSocket("ws://localhost:8080");
document.getElementById("text").innerHTML = "WebSocket instance created: " + webSocket.url; // show the URL of the WebSocket instance
</script>
</body>
</html>
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.remmymilkyway</groupId>
<artifactId>WebSocketDemo</artifactId>
<version>1.0-SNAPSHOT</version>
<name>WebSocketDemo</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>5.10.2</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>22.0.1</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>22.0.1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId>
<version>22.0.1</version>
</dependency>
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.5.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>22</source>
<target>22</target>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<executions>
<execution>
<!-- Default configuration for running with: mvn clean javafx:run -->
<id>default-cli</id>
<configuration>
<mainClass>
com.remmymilkyway.websocketdemo/com.remmymilkyway.websocketdemo.HelloApplication
</mainClass>
<launcher>app</launcher>
<jlinkZipName>app</jlinkZipName>
<jlinkImageName>app</jlinkImageName>
<noManPages>true</noManPages>
<stripDebug>true</stripDebug>
<noHeaderFiles>true</noHeaderFiles>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
module-info.java
module com.remmymilkyway.websocketdemo {
requires javafx.controls;
requires javafx.fxml;
requires javafx.web;
requires org.java_websocket;
opens com.remmymilkyway.websocketdemo to javafx.fxml;
exports com.remmymilkyway.websocketdemo;
}
Here is the output and exceptions I get when I run my application.
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
Server started
xxxx-xx-xx xx:xx:xx.xxx java[76456:7816534] +[IMKClient subclass]: chose IMKClient_Modern
xxxx-xx-xx xx:xx:xx.xxx java[76456:7816534] +[IMKInputSession subclass]: chose IMKInputSession_Modern
Server stopped
If I open web-view.html
in a browser tab, here's the additional output I get.
New connection: 127.0.0.1
Connection closed: 127.0.0.1
Summarizing our colloquy, this Q&A examines a related issue. Although outdated, the version is still supported modulo back-port latency. In this case, JDK-8331765, affecting multiple versions, is relevant. As you are using v22.0.1, which was affected, you might try a later build. I found v21.0.5 [LTS] sufficient, and @jewelsea found that v23.0.1 worked.
The way forward depends to some extent on your configuration management plan, Java support requirements, and target platforms. Among the OpenJDK releases offered by Gluon, note that release 22 does not "receive updates anymore." In particular,
We strongly encourage all our users to use either the latest version (currently 23†) or the latest version of one of the LTS releases (currently 17 and 21).
†Released October 2024; projected support until March 2025.