Commit 668dfe4b771fe06d7ab013de74e9240a929f8f6d

Authored by Thomas Ziemer
1 parent ecbbc717

feature: REST- mit WebSocket-Verbindung in Bezug bringen können

src/main/java/net/ziemers/swxercise/lg/user/service/SessionContext.java
... ... @@ -14,6 +14,8 @@ public class SessionContext implements java.io.Serializable {
14 14  
15 15 private User user = null;
16 16  
  17 + private String sessionId = "";
  18 +
17 19 public User getUser() {
18 20 return user;
19 21 }
... ... @@ -22,9 +24,21 @@ public class SessionContext implements java.io.Serializable {
22 24 this.user = user;
23 25 }
24 26  
25   - public boolean login(final User user) {
  27 + public String getSessionId() { return sessionId; }
  28 +
  29 + private void setSessionId(String sessionId) { this.sessionId = sessionId; }
  30 +
  31 + /**
  32 + * Meldet einen Benutzer in diesem Session-Kontext an.
  33 + *
  34 + * @param user das {@link User}-Objekt des Benutzers dieses Session-Kontexts
  35 + * @param sessionId die Session-Id dieser Benutzer-Session
  36 + * @return Liefert <code>true</code> zurück, wenn der Benutzer am Session-Kontext angemeldet werden konnte.
  37 + */
  38 + public boolean login(final User user, final String sessionId) {
26 39 if (getUser() == null) {
27 40 setUser(user);
  41 + setSessionId(sessionId);
28 42 return true;
29 43 }
30 44 return false;
... ...
src/main/java/net/ziemers/swxercise/lg/user/service/UserService.java
... ... @@ -34,11 +34,14 @@ public class UserService {
34 34 * Meldet den Benutzer im SessionContext an.
35 35 *
36 36 * @param dto das {@link UserDto} enthält die Eigenschaften des anzumeldenden Benutzers
  37 + * @param sessionId die Session-Id, über die diese Benutzer-Authentifizierung erfolgt
37 38 * @return <code>true</code>, wenn die Anmeldung erfolgreich war.
38 39 */
39   - public boolean loginUser(UserDto dto) {
  40 + public boolean loginUser(UserDto dto, String sessionId) {
40 41 final User user = dao.findByUsername(dto.getUsername());
41   - return user != null && user.getProfile().isValidPassword(dto.getPassword()) && sessionContext.login(user);
  42 + return user != null
  43 + && user.getProfile().isValidPassword(dto.getPassword())
  44 + && sessionContext.login(user, sessionId);
42 45 }
43 46  
44 47 /**
... ...
src/main/java/net/ziemers/swxercise/ui/UserViewController.java
... ... @@ -5,7 +5,9 @@ import java.util.Collection;
5 5 import javax.annotation.security.RolesAllowed;
6 6 import javax.enterprise.context.ApplicationScoped;
7 7 import javax.inject.Inject;
  8 +import javax.servlet.http.HttpServletRequest;
8 9 import javax.ws.rs.*;
  10 +import javax.ws.rs.core.Context;
9 11 import javax.ws.rs.core.MediaType;
10 12  
11 13 import net.ziemers.swxercise.lg.user.enums.RightState;
... ... @@ -83,6 +85,7 @@ public class UserViewController {
83 85 @RolesAllowed(RightState.Constants.LOGGED_IN)
84 86 public User getUser() {
85 87 logger.info("Trying to get user's profile info.");
  88 +
86 89 return userService.findUser(); }
87 90  
88 91 /**
... ... @@ -199,6 +202,7 @@ public class UserViewController {
199 202 * Aufruf:
200 203 * POST http://localhost:8080/swxercise/rest/v1/user/login
201 204 *
  205 + * @param request das {@link HttpServletRequest}-Objekt des augenblicklichen HTTP-Requests
202 206 * @param dto das mittels der als JSON-Objekt übergebenenen Eigenschaften zu füllende {@link UserDto}
203 207 * @return ein {@link ResponseState}-Objekt mit den Ergebnisinformationen des Aufrufs.
204 208 */
... ... @@ -207,10 +211,14 @@ public class UserViewController {
207 211 @Consumes(MediaType.APPLICATION_JSON)
208 212 @Produces(MediaType.APPLICATION_JSON)
209 213 @RolesAllowed(RightState.Constants.NOT_LOGGED_IN)
210   - public RestResponse loginUser(UserDto dto) {
211   - logger.info("Trying to log-in user '{}'.", dto.getUsername());
212   - if (userService.loginUser(dto)) {
213   - return new RestResponse();
  214 + public RestResponse loginUser(@Context HttpServletRequest request, UserDto dto) {
  215 + // wir benötigen die Session-Id später, um REST-Zugriffe mit WebSockets in Bezug zu bringen
  216 + String sessionId = request.getSession(false).getId();
  217 +
  218 + logger.info("Trying to log-in user '{}' with session id #{}.", dto.getUsername(), sessionId);
  219 +
  220 + if (userService.loginUser(dto, sessionId)) {
  221 + return new RestResponse(sessionId);
214 222 }
215 223 return new RestResponse(ResponseState.FAILED);
216 224 }
... ... @@ -229,6 +237,7 @@ public class UserViewController {
229 237 @RolesAllowed(RightState.Constants.LOGGED_IN)
230 238 public RestResponse logoutUser() {
231 239 logger.info("Trying to log-out user.");
  240 +
232 241 if (userService.logoutUser()) {
233 242 return new RestResponse();
234 243 }
... ...
src/main/java/net/ziemers/swxercise/ui/utils/RestResponse.java
... ... @@ -21,6 +21,11 @@ public class RestResponse {
21 21 this.message = message;
22 22 }
23 23  
  24 + public RestResponse(final String message) {
  25 + this();
  26 + this.message = message;
  27 + }
  28 +
24 29 public int getResponseCode() {
25 30 return responseState.getResponseCode();
26 31 }
... ...
src/main/java/net/ziemers/swxercise/ui/ws/WebSocketController.java
... ... @@ -15,8 +15,8 @@ import javax.websocket.server.PathParam;
15 15 import javax.websocket.server.ServerEndpoint;
16 16 import java.io.IOException;
17 17 import java.util.Collections;
18   -import java.util.HashSet;
19   -import java.util.Set;
  18 +import java.util.HashMap;
  19 +import java.util.Map;
20 20  
21 21 /**
22 22 * Stub für die WebSocket-Unterstützung.
... ... @@ -29,11 +29,9 @@ import java.util.Set;
29 29 decoders = { WebSocketJson.MessageDecoder.class } )
30 30 public class WebSocketController {
31 31  
32   - static final String serverEndpointPath = "/ws/api/v1/anEndpoint/{aParameter}";
  32 + static final String serverEndpointPath = "/ws/api/v1/anEndpoint/{restSessionid}";
33 33  
34   - // Eine Verknüpfung zwischen der WebSocket-Session und dem SessionContext des per REST
35   - // angemeldeten Benutzers muss irgendwie auch noch realisiert werden. :)
36   - private static Set<Session> peers = Collections.synchronizedSet(new HashSet<>());
  34 + private static Map<Session, String> peers = Collections.synchronizedMap(new HashMap<>());
37 35  
38 36 private Logger logger;
39 37  
... ... @@ -43,31 +41,37 @@ public class WebSocketController {
43 41 }
44 42  
45 43 /**
46   - * Callback-Methode für das Öffnen einer neuen WebSocket-Verbindung.
  44 + * Callback-Methode für das Öffnen einer neuen WebSocket-Verbindung. <code>restSessionId</code>
  45 + * wird benötigt, um die WebSocket-Verbindung mit einer REST-Authentifizierung in Bezug bringen
  46 + * zu können.
47 47 *
48   - * @param session das {@link Session}-Objekt der neuen WebSocket-Verbindung
  48 + * @param wsSession das {@link Session}-Objekt der neuen WebSocket-Verbindung
  49 + * @param restSessionId die Session-Id einer vorangegangenen REST-Authentifizierung
49 50 */
50 51 @OnOpen
51   - public void onOpen(Session session) {
52   - logger.info("WebSocket opened with session id #{}", session.getId());
53   - peers.add(session);
  52 + public void onOpen(Session wsSession, @PathParam("restSessionid") String restSessionId) {
  53 + logger.info("WebSocket {} opened with session id #{}", restSessionId, wsSession.getId());
  54 +
  55 + // wir können später über die gegebene WebSocket-Session die REST-Session-Id dieses WebSockets ermitteln
  56 + peers.putIfAbsent(wsSession, restSessionId);
54 57 }
55 58  
56 59 /**
57 60 * Callback-Methode, die den Empfang einer neuen WebSocket-Nachricht signalisiert.
58 61 *
59 62 * @param json der JSON-strukturierte Inhalt der WebSocket-Nachricht
60   - * @param session das {@link Session}-Objekt der sendenden WebSocket-Verbindung
  63 + * @param wsSession das {@link Session}-Objekt der sendenden WebSocket-Verbindung
61 64 */
62 65 @OnMessage
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());
  66 + public void onMessage(WebSocketJson json, Session wsSession) throws IOException, EncodeException {
  67 + // die Map liefert uns zur gegebenen WebSocket-Session die REST-Session-Id zurück
  68 + String restSessionId = peers.get(wsSession);
  69 +
  70 + logger.info("WebSocket {} Message '{}' received by session id #{}",
  71 + restSessionId, json.getMessage(), wsSession.getId());
68 72 try {
69   - // Wir senden die empfangene Nachricht gleich wieder zurück. Das Marshalling geschieht automatisch.
70   - session.getBasicRemote().sendObject(json);
  73 + // Wir senden die empfangene Nachricht gleich wieder zurück. Das JSON-Marshalling geschieht automatisch.
  74 + wsSession.getBasicRemote().sendObject(json);
71 75 } catch (IOException e) {
72 76 e.printStackTrace();
73 77 }
... ... @@ -87,12 +91,12 @@ public class WebSocketController {
87 91 * Callback-Methode für das Schließen einer geöffneten WebSocket-Verbindung.
88 92 *
89 93 * @param reason die Ursache für das Schließen der WebSocket-Verbindung
90   - * @param session das {@link Session}-Objekt der geschlossenen WebSocket-Verbindung
  94 + * @param wsSession das {@link Session}-Objekt der geschlossenen WebSocket-Verbindung
91 95 */
92 96 @OnClose
93   - public void onClose(CloseReason reason, Session session) {
94   - logger.info("Closing WebSocket due to '{}' by session id #{}", reason.getReasonPhrase(), session.getId());
95   - peers.remove(session);
  97 + public void onClose(CloseReason reason, Session wsSession) {
  98 + logger.info("Closing WebSocket due to '{}' by session id #{}", reason.getReasonPhrase(), wsSession.getId());
  99 + peers.remove(wsSession);
96 100 }
97 101  
98 102 }
... ...
src/main/webapp/websockets.html
... ... @@ -7,7 +7,10 @@
7 7  
8 8 <body>
9 9 <script>
10   - var url = "ws://localhost:8080/swxercise/ws/api/v1/anEndpoint/4711";
  10 + // sei "4711" die in einer vorangegangenen REST-Authentifizierung ermittelte "restSessionId"
  11 + var restSessionId = 4711;
  12 +
  13 + var url = "ws://localhost:8080/swxercise/ws/api/v1/anEndpoint/" + restSessionId;
11 14 var webSocket = new WebSocket(url);
12 15  
13 16 // Callback-Methoden für die WebSocket-Kommunikation
... ...