Commit 7de29276fc9114a4f4b57c9ff8f4cf20735b22b5

Authored by Thomas Ziemer
1 parent 9144b122

feature: WebSockets um ein exemplarisches JSON-Marshalling erweitert

src/main/java/net/ziemers/swxercise/ui/ws/WebSocketController.java
... ... @@ -4,7 +4,13 @@ import org.slf4j.Logger;
4 4 import org.slf4j.LoggerFactory;
5 5  
6 6 import javax.annotation.PostConstruct;
7   -import javax.websocket.*;
  7 +import javax.websocket.CloseReason;
  8 +import javax.websocket.EncodeException;
  9 +import javax.websocket.OnClose;
  10 +import javax.websocket.OnError;
  11 +import javax.websocket.OnMessage;
  12 +import javax.websocket.OnOpen;
  13 +import javax.websocket.Session;
8 14 import javax.websocket.server.PathParam;
9 15 import javax.websocket.server.ServerEndpoint;
10 16 import java.io.IOException;
... ... @@ -15,16 +21,18 @@ import java.util.Set;
15 21 /**
16 22 * Stub für die WebSocket-Unterstützung.
17 23 *
18   - * Muss bei Bedarf noch um ein JSON-Marshalling erweitert werden.
19   - *
20 24 * Aufgepasst: Mittels CDI kann nur @ApplicationScoped injiziert werden,
21 25 * da während eines WebSocket-Callbacks kein Session-Kontext aktiv ist.
22 26 */
23   -@ServerEndpoint(WebSocketController.serverEndpointPath)
  27 +@ServerEndpoint(value = WebSocketController.serverEndpointPath,
  28 + encoders = { WebSocketJson.MessageEncoder.class },
  29 + decoders = { WebSocketJson.MessageDecoder.class } )
24 30 public class WebSocketController {
25 31  
26 32 static final String serverEndpointPath = "/ws/api/v1/anEndpoint/{aParameter}";
27 33  
  34 + // Eine Verknüpfung zwischen der WebSocket-Session und dem SessionContext des per REST
  35 + // angemeldeten Benutzers muss irgendwie auch noch realisiert werden. :)
28 36 private static Set<Session> peers = Collections.synchronizedSet(new HashSet<>());
29 37  
30 38 private Logger logger;
... ... @@ -48,15 +56,18 @@ public class WebSocketController {
48 56 /**
49 57 * Callback-Methode, die den Empfang einer neuen WebSocket-Nachricht signalisiert.
50 58 *
51   - * @param message der Inhalt der WebSocket-Nachricht
  59 + * @param json der JSON-strukturierte Inhalt der WebSocket-Nachricht
52 60 * @param session das {@link Session}-Objekt der sendenden WebSocket-Verbindung
53 61 */
54 62 @OnMessage
55   - public void onMessage(String message, Session session, @PathParam("aParameter") String param) {
56   - logger.info("WebSocket Message '{}/{}' received by session id #{}", message, param, session.getId());
  63 + public void onMessage(WebSocketJson json,
  64 + Session session,
  65 + @PathParam("aParameter") String param) throws IOException, EncodeException {
  66 + logger.info("WebSocket Message '{}/{}' received by session id #{}",
  67 + json.getMessage(), param, session.getId());
57 68 try {
58   - // wir senden die empfangene Nachricht gleich wieder zurück
59   - session.getBasicRemote().sendText(String.format("%s/%s", message, param));
  69 + // Wir senden die empfangene Nachricht gleich wieder zurück. Das Marshalling geschieht automatisch.
  70 + session.getBasicRemote().sendObject(json);
60 71 } catch (IOException e) {
61 72 e.printStackTrace();
62 73 }
... ...
src/main/java/net/ziemers/swxercise/ui/ws/WebSocketJson.java 0 → 100644
  1 +package net.ziemers.swxercise.ui.ws;
  2 +
  3 +import javax.json.Json;
  4 +import javax.json.JsonObject;
  5 +import javax.json.JsonReader;
  6 +import javax.json.JsonReaderFactory;
  7 +import javax.websocket.DecodeException;
  8 +import javax.websocket.Decoder;
  9 +import javax.websocket.EncodeException;
  10 +import javax.websocket.Encoder;
  11 +import javax.websocket.EndpointConfig;
  12 +import java.io.StringReader;
  13 +import java.util.Collections;
  14 +
  15 +/**
  16 + * Ein Beispiel-JSON zur Übertragung durch den WebSocket.
  17 + */
  18 +public class WebSocketJson {
  19 +
  20 + /**
  21 + * Wandelt ein Objekt der Klasse in einen JSON-String um.
  22 + */
  23 + public static class MessageEncoder implements Encoder.Text<WebSocketJson> {
  24 +
  25 + @Override
  26 + public void init(EndpointConfig config) {
  27 + }
  28 +
  29 + @Override
  30 + public String encode(WebSocketJson message) throws EncodeException {
  31 + return Json.createObjectBuilder()
  32 + .add("username", message.getUsername())
  33 + .add("message", message.getMessage())
  34 + .build()
  35 + .toString();
  36 + }
  37 +
  38 + @Override
  39 + public void destroy() {
  40 + }
  41 +
  42 + }
  43 +
  44 + /**
  45 + * Wandelt einen JSON-String in ein Objekt der Klasse um.
  46 + */
  47 + public static class MessageDecoder implements Decoder.Text<WebSocketJson> {
  48 +
  49 + private JsonReaderFactory factory = Json.createReaderFactory(Collections.emptyMap());
  50 +
  51 + @Override
  52 + public void init(EndpointConfig config) {
  53 + }
  54 +
  55 + @Override
  56 + public WebSocketJson decode(String str) throws DecodeException {
  57 + WebSocketJson message = new WebSocketJson();
  58 + JsonReader reader = factory.createReader(new StringReader(str));
  59 + JsonObject json = reader.readObject();
  60 +
  61 + message.setUsername(json.getString("username"));
  62 + message.setMessage(json.getString("message"));
  63 +
  64 + return message;
  65 + }
  66 +
  67 + @Override
  68 + public boolean willDecode(String str) {
  69 + return true;
  70 + }
  71 +
  72 + @Override
  73 + public void destroy() {
  74 + }
  75 +
  76 + }
  77 +
  78 + /*
  79 + * Payload der JSON-Nachricht
  80 + */
  81 + private String username;
  82 +
  83 + private String message;
  84 +
  85 + private WebSocketJson() {}
  86 +
  87 + public String getUsername() {
  88 + return username;
  89 + }
  90 +
  91 + private void setUsername(String username) {
  92 + this.username = username;
  93 + }
  94 +
  95 + public String getMessage() {
  96 + return message;
  97 + }
  98 +
  99 + private void setMessage(String message) {
  100 + this.message = message;
  101 + }
  102 +
  103 +}
... ...
src/main/webapp/websockets.html
1 1 <!DOCTYPE html>
2   -<html lang="en">
3   -<head>
4   - <meta charset="UTF-8">
5   - <title>Test WebSockets</title>
6   -</head>
7   -<body>
8   - <script>
9   - var url = "ws://localhost:8080/swxercise/ws/api/v1/anEndpoint/4711";
10   - var webSocket = new WebSocket(url);
11   -
12   - // Callback-Methoden für die WebSocket-Kommunikation
13   - webSocket.onopen = function(e) { onWebSocketOpen(e) };
14   - webSocket.onclose = function(e) { onWebSocketClose(e) };
15   - webSocket.onmessage = function(e) { onWebSocketMessage(e) };
16   - webSocket.onerror = function(e) { onWebSocketError(e) };
17   -
18   - function onWebSocketOpen(e) {
19   - console.log("WebSocket has been opened.");
20   - }
21   -
22   - function onWebSocketClose(e) {
23   - console.log("WebSocket has been closed.");
24   - }
25   -
26   - function onWebSocketMessage(e) {
27   - console.log("WebSocket Message '" + e.data + "' has been received.");
28   - }
29   -
30   - function onWebSocketError(e) {
31   - alert("WebSocket Error " + e + " has been thrown!");
32   - }
33   -
34   - function sendWebSocketMessage() {
35   - webSocket.send('Hello World!');
36   - console.log("Tried to send WebSocket Message.");
37   - }
38   - </script>
39   - <button onclick="sendWebSocketMessage()">Klick mich.</button>
40   -</body>
  2 +<html lang="de">
  3 + <head>
  4 + <meta charset="UTF-8">
  5 + <title>Test WebSockets</title>
  6 + </head>
  7 +
  8 + <body>
  9 + <script>
  10 + var url = "ws://localhost:8080/swxercise/ws/api/v1/anEndpoint/4711";
  11 + var webSocket = new WebSocket(url);
  12 +
  13 + // Callback-Methoden für die WebSocket-Kommunikation
  14 + webSocket.onopen = function(e) { onWebSocketOpen(e) };
  15 + webSocket.onclose = function(e) { onWebSocketClose(e) };
  16 + webSocket.onmessage = function(e) { onWebSocketMessage(e) };
  17 + webSocket.onerror = function(e) { onWebSocketError(e) };
  18 +
  19 + function onWebSocketOpen(e) {
  20 + console.log("WebSocket has been opened.");
  21 + }
  22 +
  23 + function onWebSocketClose(e) {
  24 + console.log("WebSocket has been closed.");
  25 + }
  26 +
  27 + function onWebSocketMessage(e) {
  28 + // JSON-String in ein JavaScript-Objekt konvertieren
  29 + var json = JSON.parse(e.data);
  30 +
  31 + console.log("WebSocket Message '" + json.message + "' has been received.");
  32 + }
  33 +
  34 + function onWebSocketError(e) {
  35 + alert("WebSocket Error " + e + " has been thrown!");
  36 + }
  37 +
  38 + function sendWebSocketMessage() {
  39 + var json = {
  40 + "username": "admin",
  41 + "message": "Hello World!"
  42 + }
  43 +
  44 + // JavaScript-Objekt in einen JSON-String konvertieren
  45 + webSocket.send(JSON.stringify(json));
  46 +
  47 + console.log("Tried to send WebSocket Message.");
  48 + }
  49 + </script>
  50 + <button onclick="sendWebSocketMessage()">Klick mich.</button>
  51 + </body>
41 52 </html>
42 53 \ No newline at end of file
... ...