From dc79ea14ccfd9680e94c348921baed660a7a6c80 Mon Sep 17 00:00:00 2001 From: Jonas Meeuws Date: Thu, 28 Mar 2024 16:56:38 +0100 Subject: [PATCH 1/4] Added websocket endpoint and singleton for sending messages from any class. --- build.gradle | 3 ++ src/main/java/telraam/App.java | 12 +++++- .../websocket/WebSocketConnection.java | 41 +++++++++++++++++++ .../websocket/WebSocketMessageSingleton.java | 37 +++++++++++++++++ 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 src/main/java/telraam/websocket/WebSocketConnection.java create mode 100644 src/main/java/telraam/websocket/WebSocketMessageSingleton.java diff --git a/build.gradle b/build.gradle index 1d4df44..6800130 100644 --- a/build.gradle +++ b/build.gradle @@ -21,6 +21,7 @@ sourceCompatibility = 17 // Set our project variables project.ext { dropwizardVersion = '4.0.5' + jettyVersion = '11.0.19' } repositories { @@ -62,6 +63,8 @@ dependencies { 'io.dropwizard:dropwizard-hibernate:' + dropwizardVersion, 'io.dropwizard:dropwizard-auth:' + dropwizardVersion, 'io.dropwizard:dropwizard-jdbi3:' + dropwizardVersion, + 'org.eclipse.jetty.websocket:websocket-jetty-api:' + jettyVersion, + 'org.eclipse.jetty.websocket:websocket-jetty-server:' + jettyVersion, ) // Database implementation('com.h2database:h2:2.2.220') diff --git a/src/main/java/telraam/App.java b/src/main/java/telraam/App.java index 8729ea2..d7bfdba 100644 --- a/src/main/java/telraam/App.java +++ b/src/main/java/telraam/App.java @@ -11,6 +11,7 @@ import jakarta.servlet.DispatcherType; import jakarta.servlet.FilterRegistration; import org.eclipse.jetty.servlets.CrossOriginFilter; +import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer; import org.jdbi.v3.core.Jdbi; import telraam.api.*; import telraam.database.daos.*; @@ -21,6 +22,7 @@ import telraam.logic.robust.RobustLapper; import telraam.station.Fetcher; import telraam.util.AcceptedLapsUtil; +import telraam.websocket.WebSocketConnection; import java.io.IOException; import java.util.EnumSet; @@ -78,6 +80,15 @@ public void run(AppConfiguration configuration, Environment environment) throws // Initialize AcceptedLapUtil AcceptedLapsUtil.createInstance(this.database); + // Register websocket endpoint + JettyWebSocketServletContainerInitializer.configure( + environment.getApplicationContext(), + (servletContext, wsContainer) -> { + wsContainer.setMaxTextMessageSize(65535); + wsContainer.addMapping("/ws", (req, res) -> new WebSocketConnection()); + } + ); + // Add api resources JerseyEnvironment jersey = environment.jersey(); jersey.register(new BatonResource(database.onDemand(BatonDAO.class))); @@ -94,7 +105,6 @@ public void run(AppConfiguration configuration, Environment environment) throws jersey.register(new MonitoringResource(database)); environment.healthChecks().register("template", new TemplateHealthCheck(configuration.getTemplate())); - // Enable CORS final FilterRegistration.Dynamic cors = environment.servlets().addFilter("CORS", CrossOriginFilter.class); diff --git a/src/main/java/telraam/websocket/WebSocketConnection.java b/src/main/java/telraam/websocket/WebSocketConnection.java new file mode 100644 index 0000000..191fea0 --- /dev/null +++ b/src/main/java/telraam/websocket/WebSocketConnection.java @@ -0,0 +1,41 @@ +package telraam.websocket; + +import java.io.IOException; +import java.util.logging.Logger; + +import org.eclipse.jetty.websocket.api.Session; +import org.eclipse.jetty.websocket.api.WebSocketAdapter; + +public class WebSocketConnection extends WebSocketAdapter { + private static final Logger logger = Logger.getLogger(WebSocketConnection.class.getName()); + + @Override + public void onWebSocketConnect(Session session) { + super.onWebSocketConnect(session); + WebSocketMessageSingleton.getInstance().registerConnection(this); + logger.info("Instance with remote \"%s\" connected".formatted(getRemote().getRemoteAddress())); + } + + @Override + public void onWebSocketClose(int statusCode, String reason) { + super.onWebSocketClose(statusCode, reason); + WebSocketMessageSingleton.getInstance().unregisterConnection(this); + logger.info("Instance with remote \"%s\" closed: [%s] %s".formatted(getRemote().getRemoteAddress(), statusCode, reason)); + } + + @Override + public void onWebSocketError(Throwable cause) { + super.onWebSocketError(cause); + logger.severe("WebSocket error in instance with remote \"%s\": %s".formatted(getRemote().getRemoteAddress(), cause)); + } + + public void send(String s) { + try { + getRemote().sendString(s); + } catch (IOException e) { + logger.severe("Sending \"%s\" through instance with remote \"%s\" failed with %s".formatted(s, getRemote().getRemoteAddress(), e)); + return; + } + logger.finest("Sent \"%s\" through instance with remote \"%s\"".formatted(s, getRemote().getRemoteAddress())); + } +} diff --git a/src/main/java/telraam/websocket/WebSocketMessageSingleton.java b/src/main/java/telraam/websocket/WebSocketMessageSingleton.java new file mode 100644 index 0000000..9749d6d --- /dev/null +++ b/src/main/java/telraam/websocket/WebSocketMessageSingleton.java @@ -0,0 +1,37 @@ +package telraam.websocket; + +import lombok.Getter; + +import java.util.HashSet; +import java.util.Set; +import java.util.logging.Logger; + +public class WebSocketMessageSingleton { + private static final Logger logger = Logger.getLogger(WebSocketMessageSingleton.class.getName()); + + @Getter + private static final WebSocketMessageSingleton instance = new WebSocketMessageSingleton(); + private static final Set registeredConnections = new HashSet<>(); + + private WebSocketMessageSingleton() { + } + + public void registerConnection(WebSocketConnection conn) { + boolean modified = registeredConnections.add(conn); + if (modified) { + logger.info("Registered WebSocketConnection %s".formatted(conn)); + } + } + + public void unregisterConnection(WebSocketConnection conn) { + boolean modified = registeredConnections.remove(conn); + if (modified) { + logger.info("Unregistered WebSocketConnection %s".formatted(conn)); + } + } + + public void sendToAll(String s) { + logger.info("Sending \"%s\" to all registered WebSocketConnection instances".formatted(s)); + registeredConnections.forEach(conn -> conn.send(s)); + } +} From b5833b2f7ca20fe1c6ae0665526bd3766acf002f Mon Sep 17 00:00:00 2001 From: Jonas Meeuws Date: Thu, 28 Mar 2024 22:27:21 +0100 Subject: [PATCH 2/4] Add websocket send example in TeamResource::create() Should close #111 when merged --- src/main/java/telraam/api/TeamResource.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/telraam/api/TeamResource.java b/src/main/java/telraam/api/TeamResource.java index 64201dd..22c36a6 100644 --- a/src/main/java/telraam/api/TeamResource.java +++ b/src/main/java/telraam/api/TeamResource.java @@ -16,6 +16,8 @@ import java.util.Objects; import java.util.Optional; +import telraam.websocket.WebSocketMessageSingleton; + @Path("/team") @Tag(name="Team") @@ -48,6 +50,14 @@ public int create(Team team) { )); } + WebSocketMessageSingleton.getInstance().sendToAll( + "new team (%s, %s, %s)".formatted( + team.getName(), + team.getId(), + team.getBatonId() + ) + ); + return ret; } From a1f9ee1ff8ba6019316da01c5258dc1f05dea4ba Mon Sep 17 00:00:00 2001 From: Jonas Meeuws Date: Thu, 28 Mar 2024 23:06:10 +0100 Subject: [PATCH 3/4] change sendToAll log level: info -> finest --- src/main/java/telraam/websocket/WebSocketMessageSingleton.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/telraam/websocket/WebSocketMessageSingleton.java b/src/main/java/telraam/websocket/WebSocketMessageSingleton.java index 9749d6d..de12115 100644 --- a/src/main/java/telraam/websocket/WebSocketMessageSingleton.java +++ b/src/main/java/telraam/websocket/WebSocketMessageSingleton.java @@ -31,7 +31,7 @@ public void unregisterConnection(WebSocketConnection conn) { } public void sendToAll(String s) { - logger.info("Sending \"%s\" to all registered WebSocketConnection instances".formatted(s)); + logger.finest("Sending \"%s\" to all registered WebSocketConnection instances".formatted(s)); registeredConnections.forEach(conn -> conn.send(s)); } } From 5d42686d1b858a6371ca3f540e50472065028106 Mon Sep 17 00:00:00 2001 From: Topvennie Date: Fri, 29 Mar 2024 00:53:35 +0100 Subject: [PATCH 4/4] Removed websocket message --- src/main/java/telraam/api/TeamResource.java | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/main/java/telraam/api/TeamResource.java b/src/main/java/telraam/api/TeamResource.java index 22c36a6..56975c9 100644 --- a/src/main/java/telraam/api/TeamResource.java +++ b/src/main/java/telraam/api/TeamResource.java @@ -2,22 +2,20 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; import telraam.database.daos.BatonSwitchoverDAO; import telraam.database.daos.TeamDAO; import telraam.database.models.BatonSwitchover; import telraam.database.models.Team; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.core.MediaType; import java.sql.Timestamp; import java.time.Instant; import java.util.List; import java.util.Objects; import java.util.Optional; -import telraam.websocket.WebSocketMessageSingleton; - @Path("/team") @Tag(name="Team") @@ -50,14 +48,6 @@ public int create(Team team) { )); } - WebSocketMessageSingleton.getInstance().sendToAll( - "new team (%s, %s, %s)".formatted( - team.getName(), - team.getId(), - team.getBatonId() - ) - ); - return ret; }