Changes for page Basisprojekt

Last modified by mgrawunder on 2025/09/09 08:42

edited by mgrawunder
on 2025/09/03 10:47
Change comment: There is no comment for this version
To version arrow_back 60.1
edited by mgrawunder
on 2025/09/09 08:42
Change comment: There is no comment for this version

Summary

Details

insert_drive_file Page properties
Content
... ... @@ -11,17 +11,57 @@
11 11  
12 12  == Clone ==
13 13  
14 +Achtung! In dem Screenshot wird das globale Basisprojekt verwendet. Für jede Gruppe existiert bereits ein eigenes Repository, welches verwendet werden sollte,
15 +
16 +Sie finden die Clone-URL wie folgt:
17 +
18 +* Loggen Sie sich auf [[https:~~/~~/gitlab.swl.informatik.uni-oldenburg.de/>>https://gitlab.swl.informatik.uni-oldenburg.de/]] ein
19 +* Falls nicht vorausgewählt, wählen Sie auf der linken Seite "Projects"
20 +[[image:1757398628416-879.png||height="119" width="541"]]
21 +* Da Sie bisher noch nichts gemacht haben, ist diese Seite leer. Wechseln Sie auf den Reiter Member
22 +* Dort sollte ihr Repository zu finden sein.
23 +* Oben rechts gibt es einen Button Code. Kopieren Sie dort die URL, die hinter "Clone with HTTPS" steht.
24 +[[image:1757398731084-704.png||height="454" width="323"]]
25 +
14 14  [[image:1755245971657-468.png]]
15 15  
28 +== Access Token ==
16 16  
30 +Beim ersten Mal clonen müssen Sie Ihre Gitlab-Zugangsdaten verwenden. Statt Name und Passwort ist es sinnvoll, einen Access-Token zu definieren. Das können Sie machen, in dem Sie auf ihre Profilbild klicken (auf der linken Seite) und dort "Edit Profile" auswählen. In dem nun folgenden Menü gibt es den Punkt Access tokens.
31 +
32 +[[image:1757398899497-714.png||height="246" width="278"]]
33 +
34 +Dort können Sie mit [[image:1757398947128-748.png||height="89" width="197"]] ein neues Token anlegen.
35 +
36 +Als Namen können Sie z.B. IntelliJ verwenden. Wichtig! Das Token ist aus Sicherheitsgründen nur eine bestimmte Zeit gültig. In diesem Gitlab kann dies maximal ein Jahr sein, standardmäßig ist ist hier aber ein Monat gewählt. Sie sollten also das Feld anpassen.
37 +
38 +[[image:1757399088336-273.png||height="92" width="547"]]
39 +
40 +Bei den Scopes sollten die beiden Rechte "read_repository" und "write_repository" gewählt werden.
41 +
42 +Danach wird das Access Token generiert
43 +
44 +[[image:1757399184270-348.png||height="99" width="978"]]
45 +
46 +Jetzt ist es wichtig, dass Sie sich das Token sichern!
47 +
48 +Beim Einloggen in IntelliJ können Sie dieses Token im Passwort-Feld verwenden. Geben Sie ihren Account bei Name ein.
49 +
50 +== Nach dem Clonen ==
51 +
52 +sollten Sie einen Bildschirm ähnlich zu dem folgenden sehen:
53 +
17 17  [[image:1755245980026-164.png]]
18 18  
19 -Auf anderen Branch wechseln (hier development)
56 +Auf dem main-Branch (master) kann keine Änderung gemacht werden, deswegen muss auf einen anderen Branch gewechselt werden. Im Beispiel development.
20 20  
21 21  [[image:1755245996886-733.png]]
22 22  
23 23  == Initialer Build (Generierung) ==
24 24  
62 +Dem neuen Code fehlen einige generierte Dateien. Diese werden wie folgt erzeugt. 
63 +Hinweis: Immer, wenn an dem OpenAPI-Dokument etwas geändert wird oder neue Abhängigkeiten für Maven definiert werden, muss diese Aktion durchgeführt werden.
64 +
25 25  [[image:1755246008466-477.png]]
26 26  
27 27  
... ... @@ -40,10 +40,12 @@
40 40  
41 41  == Server laufen lassen ==
42 42  
83 +Den Serverbereich aufklappen und dort auf die Datei ServerApp mit der rechten Maustaste klicken.
84 +
43 43  [[image:1755246035428-328.png]]
44 44  
45 45  
46 -... und ggf. Lombok aktivieren (Man wird nach dem Start der Anwendung gefragt)
88 +... und ggf. Lombok aktivieren (Man wird nach dem Start der Anwendung gefragt). WICHTIG! Wenn das Lombok-Plugin nicht installiert und die folgende Funktion nicht aktiviert ist, muss jede Änderung mit Hilfe von Maven passieren.
47 47  
48 48  [[image:1755246072443-191.png]]
49 49  
... ... @@ -53,6 +53,8 @@
53 53  
54 54  == Logging umstellen ==
55 55  
98 +Wenn man möchte, kann man das Logging umstellen.
99 +
56 56  [[image:1755246135109-325.png]]
57 57  
58 58  
... ... @@ -63,8 +63,12 @@
63 63  
64 64  == Development Profil aktivieren ==
65 65  
66 -damit dann user1 - user9 angelegt werden und man nicht jedesmal neu registrieren muss
110 +Damit das Testen einfacher geht, gibt es ein spezielles Spring-Profil. In diesem werden automatisch user1-user9 mit jeweils dem identischen Passwort angelegt und man spart sich die Registierung.
67 67  
112 +Wenn man die Anwendung einmal gestartet hat, kann man dies Configuration anpassen:
113 +
114 +[[image:1757399848941-253.png||height="209" width="558"]]
115 +
68 68  [[image:1755246173415-934.png]]
69 69  
70 70  
... ... @@ -74,9 +74,14 @@
74 74  
75 75  [[image:1755248752596-839.png]]
76 76  
125 +Danach muss man den Server neu starten!
77 77  
78 78  == Client starten ==
79 79  
129 +Wenn der Server gestartet ist, kann man mehrere Clients starten. Dafür auf jeden Fall die Klasse Main verwenden.
130 +
131 +**Sollte es nun Problem geben, schauen Sie bitte, ob Sie noch eine alte Java-Version auf ihrem System installiert haben. Wir brauchen mindestens Java 21!**
132 +
80 80  [[image:1755246257400-525.png]]
81 81  
82 82  
... ... @@ -88,6 +88,8 @@
88 88  
89 89  === Mehrere Instanzen des Clients ermöglichen ===
90 90  
144 +Standardmäßig erlaubt IntelliJ nicht das Starten mehrerer Clients. Man könnte nun mehrere Configurations für den Client anlegen. Man kann aber auch in der Konfiguration unter "Modify options" den Haken bei "Allow multiple instances" setzen. Dann kann eine beliebige Anzahl von Clients gestartet werden.
145 +
91 91  [[image:1755246233218-893.png]]
92 92  
93 93  
... ... @@ -219,7 +219,7 @@
219 219  *ApiController implements *Api (Für Spring) (z.B. LobbiesApiController)
220 220  )))
221 221  * (((
222 -*ApiDelegate (z.B. LobbiesApiDelegate): Macht die eigentliche Arbeit und muss** im eigenen Code-Bereich** erweitert werden!
277 +*ApiDelegate (z.B. LobbiesApiDelegate): Macht die eigentliche Arbeit und muss** im eigenen Code-Bereich** erweitert werden!
223 223  )))
224 224  
225 225  
... ... @@ -246,3 +246,173 @@
246 246  1. Schließlich wird am Ende gesagt, dass alles ok ist und eine Antwort ResponseEntity.ok mit dem Rückgabeobjekt (lobbies) gesendet.
247 247  
248 248  **Anmerkung**: Das Basisprojekt ist aktuell so eingerichtet, dass Spring Exceptions auffängt und entsprechend an den Client leitet. Diese findet in der Klasse  GlobalExceptionHandler statt
304 +
305 +Auf Server-Seite fehlt jetzt noch die Methode getLobbies im LobbyManagement
306 +
307 +[[image:1756889590500-656.png||height="81" width="518"]]
308 +
309 +
310 +=== LobbyMapping ===
311 +
312 +Da man relativ oft Server-Objekt in DTO umwandeln muss gibt es im Basisprojekt MapStruct. Damit muss man nur die DTO-Klasse anlegen (i.d.R. über OpenAPI!!)
313 +
314 +Also z.B.
315 +
316 +[[image:1756889440395-856.png]]
317 +
318 +und definiert ein Interface mit einer Annotation
319 +
320 +[[image:1756889472103-847.png]]
321 +
322 +und damit kann man die Funktion aufrufen. Hinweis: Der Mapper ist im LobbyService über die Spring Dependency Injection gebunden.
323 +
324 +== Schritt 3: Erweiterung auf Client-Seite (Java) ==
325 +
326 +Hinweis: Das Beispiel bezieht sich hier auf eine Client mit Java. Für andere Clients wie Angular ist das Vorgehen anders.
327 +
328 +Auf der Client-Seite wird die komplette Kommunikation mit dem Server in der generierten Klasse DefaultApi gekapselt.
329 +
330 +[[image:1756889795622-530.png]]
331 +
332 +Dort gibt es eine neue Methode lobbyList. Die sorgt dafür, dass der REST-Aufruf auf die Server-Seite geht und liefert das passende Objekt List<LobbyDTO> zurück
333 +
334 +Im Client gibt es auch eine Klasse LobbyService. Dort ist die DefaultApi Klasse über Dependency Injection gebunden.
335 +
336 +[[image:1756889917681-650.png]]
337 +
338 +Dort kann man nun eine neue Methode getLobbies() integrieren:
339 +
340 +[[image:1756889979252-910.png]]
341 +
342 +Und das Ganze dann z.B. im MainMenuPresenter verwenden:
343 +
344 +[[image:1756890010118-149.png||height="116" width="972"]]
345 +
346 +Anmerkung: Obwohl DefaultApi alle Funktionen zum Server kapselt, sollte man im Client spezifische Services für bestimmte Bereich haben, die diese Klasse verwenden.  Das führt zu einer besseren Trennung von Funktionalitäten im Code.
347 +
348 +
349 += Kommunikation: Server ~-~-> Client (WebSockets) =
350 +
351 +[[image:1756890800817-370.png||height="604" width="1121"]]
352 +
353 +Da man mit REST nicht Nachrichten vom Server an den Client schicken kann, werden im Basisprojekt dafür WebSockets verwendet.
354 +
355 +Spring bietet eine native Unterstützung von WebSockets. Für eigene Funktionen kann man sich in die Kommunikation über die Serverklasse WebSocketHandler einklinken
356 +
357 +
358 +[[image:1756890924024-346.png||height="377" width="1092"]]
359 +
360 +
361 +Sobald sich jemand beim Server für WebSockets angemeldet hat wird von Spring ein org.springframework.web.socket.messaging.SessionConnectedEvent
362 +geworfen, welches in der folgenden Methode (im WebSocketHandler) aufgefangen wird
363 +
364 +[[image:1756890958794-603.png||height="373" width="1087"]]
365 +
366 +Die Methode ist Observer für das Event SessionConnectedEvent
367 +
368 +Der WebSocketServer kennt die Nutzer und erlaubt das Einloggen nur, wenn Login und Passwort stimmen (durch Spring Security)
369 +
370 +[[image:1756891019715-621.png]]
371 +
372 +1)Aus dem Event kann der Nutzer gelesen werden (der sollte nie leer sein)
373 +
374 +2) Dann wird sich aus dem Repository (später mehr) der Nutzer geholt, der durch den Namen identifiziert ist (z.B. „test1“)
375 +
376 +3) Schließlich werden allen anderen darüber informiert, dass ein neuer Nutzer da ist
377 +
378 +== STOMP ==
379 +
380 +WebSockets haben kein Protokoll (wie z.B. http)
381 +
382 +Es können entweder binäre oder textuelle Daten verarbeitet werden (die jeweiligen Gegenstellen müssen das wissen!)
383 +
384 +Wenn man jetzt mehr als nur Text verschicken möchte, muss man sich überlegen, wie man Objekte z.B. mit JSON serialisiert (analog zu REST)
385 +
386 +STOMP: Streaming Text Oriented Messaging Protocol
387 +
388 +Definiert ein einfaches Protokoll, welches es erlaubt, sinnvoll über WebSockets zu kommunizieren
389 +
390 +Ist ein Teil von Spring
391 +
392 +Methoden sind z.B. CONNECT, SEND oder SUBSCRIBE
393 +
394 +STOMP arbeitet mit Topics
395 +
396 +Ein Client registriert (SUBSCRIBE) sich für bestimmte Ereignistypen
397 +
398 +
399 +§Wenn auf der Server-Seite dieser Typ veröffentlich wird dann wird dies an die jeweils interessierten Clients geschickt
400 +
401 +Publish/Subscribe-Pattern
402 +
403 +[[https:~~/~~/docs.spring.io/spring-framework/reference/web/websocket/stomp.html>>url:https://docs.spring.io/spring-framework/reference/web/websocket/stomp.html]]
404 +
405 +
406 +§Der Server definiert unterschiedliche Topics (je nach Modul)
407 +
408 +§Beim Nutzermanagement aktuell:
409 +
410 +§/topic/users/loggedIn: Es hat sich ein neuer Nutzer angemeldet
411 +
412 +§/topic/users/loggedOut: Ein Nutzer hat sich ausgeloggt
413 +
414 +
415 +[[image:1756891125969-748.png||height="317" width="726"]]
416 +
417 +§Topic-Namen sind Strings, sollte aber Aufbau von oben entsprechen
418 +
419 +§In der Lobby würde es stattdessen /topic/lobbies/* heißen
420 +
421 +== WebSockets: Versenden von Nachrichten ==
422 +
423 +[[image:1756891180516-843.png||height="426" width="801"]]
424 +
425 +[[image:1756891216134-578.png||height="428" width="699"]]
426 +
427 +== Nachrichteninhalt ==
428 +
429 +[[image:1756891254830-647.png||height="101" width="777"]]
430 +
431 +* message kann grundsätzlich alles sein, was serialisiert werden kann
432 +* Man könnte nun einfach die Java-Serialisierung verwenden (im alten Basisprojekt ist das auch so)
433 +* Das hat aber eine Reihe von Nachteilen
434 +** Der Empfänger muss dafür unbedingt auch ein Java-Client sein und er muss exakt dieselbe Klasse bei sich haben, damit der das Objekt wieder zurück in ein Java-Objekt umwandeln kann
435 +** Es gibt eine Reihe von Sicherheitsproblemen
436 +* Besser: Definiere ein gemeinsames Austauschformat, was viele verstehen ~-~-> Im Basisprojekt (und in vielen anderen Projekten auch) JSON verwenden
437 +* Insbesondere Web-Clients (JavaScript) bieten hervorragende Möglichkeiten, an JSON zu verarbeiten
438 +* Client und Server haben sich damit auf Format für den Austausch geeinigt
439 +** Topic: Strings
440 +** Message: JSON
441 +
442 +An den Clilent werden auch bei WebSockets nur DTOs verschickt! (userMapping)
443 +
444 +[[image:1756891375095-158.png||height="266" width="775"]]
445 +
446 +== Wie verbindet sich ein Client mit dem Server? ==
447 +
448 +UserService bietet eine Methode zum Login an. Diese ruft nun aber keine REST-Endpunkt auf (da man sich sowieso bei JEDEM Aufruf authentifizieren muss, macht so ein Endpunkt kein Sinn). Stattdessen wird die Verbindung mit dem WebSocket hergestellt und dort Nama und Passwort überprüft.
449 +
450 +[[image:1756891512330-186.png||height="170" width="820"]]
451 +
452 +=== Auf Server Seite (WebSocketConnectionManager): ===
453 +
454 +[[image:1756891551794-161.png||height="387" width="1019"]]
455 +
456 +1) Variablen definieren
457 +
458 +2) WebSocketClient erzeugen
459 +
460 +3) Daraus WebSocketStompClient machen
461 +
462 +4) Jackson als Mapper definieren (DTO-Object <-> JSON)
463 +
464 +=== [[image:1756891617399-232.png||height="289" width="1006"]] ===
465 +
466 +
467 +1) Asynchron die Verbindung zum Server aufbauen
468 +
469 +2) Wenn erfolgreich in das Hauptmenü wechseln (showScene à später mehr)
470 +
471 +3) Über den Kontext ein Event pushen LoggedInEvent
472 +
473 +4) Jede Serververbindung hat eine Session
attach_file 1756889440395-856.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +55.9 KB
Content info
attach_file 1756889472103-847.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +11.1 KB
Content info
attach_file 1756889590500-656.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +4.8 KB
Content info
attach_file 1756889795622-530.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +379.7 KB
Content info
attach_file 1756889917681-650.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +6.0 KB
Content info
attach_file 1756889979252-910.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +4.0 KB
Content info
attach_file 1756890010118-149.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +16.8 KB
Content info
attach_file 1756890800817-370.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +61.9 KB
Content info
attach_file 1756890924024-346.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +54.8 KB
Content info
attach_file 1756890958794-603.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +32.6 KB
Content info
attach_file 1756891019715-621.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +58.6 KB
Content info
attach_file 1756891125969-748.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +37.9 KB
Content info
attach_file 1756891180516-843.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +153.4 KB
Content info
attach_file 1756891216134-578.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +246.0 KB
Content info
attach_file 1756891254830-647.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +11.0 KB
Content info
attach_file 1756891375095-158.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +33.2 KB
Content info
attach_file 1756891512330-186.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +43.0 KB
Content info
attach_file 1756891551794-161.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +53.9 KB
Content info
attach_file 1756891617399-232.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +49.9 KB
Content info
attach_file 1757398628416-879.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +16.4 KB
Content info
attach_file 1757398731084-704.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +102.1 KB
Content info
attach_file 1757398899497-714.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +38.3 KB
Content info
attach_file 1757398947128-748.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +8.6 KB
Content info
attach_file 1757399088336-273.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +19.6 KB
Content info
attach_file 1757399184270-348.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +18.0 KB
Content info
attach_file 1757399848941-253.png
Author
... ... @@ -1,0 +1,1 @@
1 +XWiki.mgrawunder
Size
... ... @@ -1,0 +1,1 @@
1 +42.9 KB
Content info