Skip to content

Commit

Permalink
Merge pull request #17 from BlazingTwist/5-ServerSentEvents
Browse files Browse the repository at this point in the history
Beispiel für WebSocket handling mit Undertow und JavaScript
  • Loading branch information
BlazingTwist authored Dec 13, 2023
2 parents ac6da06 + 05a06b2 commit d4d7d21
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 38 deletions.
56 changes: 32 additions & 24 deletions src/main/java/example/undertow/UndertowWebsocket.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.DeploymentManager;
import io.undertow.websockets.WebSocketConnectionCallback;
import io.undertow.websockets.core.AbstractReceiveListener;
import io.undertow.websockets.core.BufferedTextMessage;
import io.undertow.websockets.core.WebSocketChannel;
import io.undertow.websockets.core.WebSockets;
import io.undertow.websockets.spi.WebSocketHttpExchange;
Expand All @@ -18,29 +20,13 @@

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class UndertowWebsocket {
private static final Logger logger = LoggerFactory.getLogger(UndertowWebsocket.class);

public static void main(String[] args) throws ServletException, IOException {
SocketHandler socketHandler = new SocketHandler();
new Thread(() -> {
while (true) {
try {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
break;
}
logger.info("Notifying channel.");
socketHandler.notifyChannel();
} catch (Exception ignore) {

}
}
}).start();

DeploymentInfo deployment = Servlets.deployment()
.setClassLoader(UndertowWebsocket.class.getClassLoader())
.setContextPath("")
Expand All @@ -51,7 +37,7 @@ public static void main(String[] args) throws ServletException, IOException {
manager.deploy();
HttpHandler handler = manager.start();
PathHandler pathHandler = Handlers.path(handler)
.addPrefixPath("/websocket", Handlers.websocket(socketHandler));
.addPrefixPath("/websocket", Handlers.websocket(new SocketHandler()));

Undertow server = Undertow.builder()
.addHttpListener(8880, "localhost")
Expand All @@ -61,19 +47,41 @@ public static void main(String[] args) throws ServletException, IOException {
logger.info("Server started");
}

public static class SocketHandler implements WebSocketConnectionCallback {
private List<WebSocketChannel> channel = new ArrayList<>();
public static class SocketHandler extends AbstractReceiveListener implements WebSocketConnectionCallback {
private final List<WebSocketChannel> channels = new ArrayList<>();

@Override
public void onConnect(WebSocketHttpExchange exchange, WebSocketChannel channel) {
logger.info("onConnect");
this.channel.add(channel);
this.channels.add(channel);

channel.getReceiveSetter().set(this);
channel.resumeReceives();
}

public void notifyChannel() {
for (WebSocketChannel c : channel) {
WebSockets.sendText("Hallo Welt!", c, null);
@Override
protected void onFullTextMessage(WebSocketChannel channel, BufferedTextMessage message) {
String msgText = message.getData();
logger.info("Received message {}", msgText);
notifyChannels(msgText);
}

public void notifyChannels(String message) {
int numChannelsNotified = 0;
int numChannelsDropped = 0;
Iterator<WebSocketChannel> iterator = channels.iterator();
while (iterator.hasNext()) {
WebSocketChannel channel = iterator.next();
if (channel.getCloseCode() >= 0) {
iterator.remove();
numChannelsDropped++;
continue;
}

WebSockets.sendText(message, channel, null);
numChannelsNotified++;
}
logger.info("Notified {} channels, dropped {} channels", numChannelsNotified, numChannelsDropped);
}
}
}
7 changes: 3 additions & 4 deletions src/main/java/logback/LogbackLoggerConfigurator.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.spi.ContextAwareBase;

import java.util.Arrays;
import java.util.List;

public class LogbackLoggerConfigurator extends ContextAwareBase implements Configurator {

private static final String LOG_FILE = "logs/jChess.log";

@SuppressWarnings("CommentedOutCode")
@Override
public ExecutionStatus configure(LoggerContext context) {
ConsoleAppender<ILoggingEvent> consoleAppender = createConsoleAppender();
Expand All @@ -32,10 +32,9 @@ public ExecutionStatus configure(LoggerContext context) {
rootLogger.addAppender(fileAppender);

// if a specific package logger is too vocal, you can silence it like this:
/*
List<OutputStreamAppender<ILoggingEvent>> appenders = Arrays.asList(consoleAppender, fileAppender);
configureLogger(context, Level.WARN, appenders, "io.undertow");
*/
configureLogger(context, Level.INFO, appenders, "io.undertow");
configureLogger(context, Level.INFO, appenders, "org.xnio");

return ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY;
}
Expand Down
50 changes: 40 additions & 10 deletions src/main/resources/webExample/websocket.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,48 @@
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.message-entry {
left: 20px;
right: 20px;
margin: 3px;
padding: 3px;
color: white;
}
</style>
<script src="Templating.js"></script>
</head>
<body>
<script>
let socket = new WebSocket("ws://localhost:8880/websocket");
socket.addEventListener("open", (event) => {
socket.send("Hello Server!");
});
<div style="display: flex; flex-direction: column; gap: 20px; justify-content: center; align-items: center">
<div style="display: flex; flex-direction: row; gap: 10px; align-items: center; flex-basis: 0; width: 100%">
<label for="messageInput">Nachricht</label>
<textarea id="messageInput" name="messageInput" rows="4" style="flex-grow: 1"></textarea>
<button onclick="sendRequest()">Nachricht Senden</button>
</div>
<div id="messagePanel" style="display: flex; flex-direction: column; gap: 10px; background-color: #666666; border-radius: 5px; border: 1px solid #777777; width: 95vw; align-items: start">
<div class="message-entry" style="font-size: 1.25em;">
Erhaltene Nachrichten
</div>
</div>
</div>

// Listen for messages
socket.addEventListener("message", (event) => {
console.log("Message from server ", event.data);
});
</script>
<script>
let socket = new WebSocket("ws://localhost:8880/websocket");

// Listen for messages
socket.addEventListener("message", (event) => {
let message = event.data;
console.log("Message from server ", message);

let messageDiv = Templating.html(`<div class="message-entry">${message}</div>`).element;
document.getElementById("messagePanel").appendChild(messageDiv);
});

function sendRequest() {
let message = document.getElementById("messageInput").value;
console.log("Sending message: '" + message + "'");
socket.send(message);
}
</script>
</body>
</html>

0 comments on commit d4d7d21

Please sign in to comment.