diff --git a/STOMP_README.md b/STOMP_README.md
index 3f874b3..3a98068 100644
--- a/STOMP_README.md
+++ b/STOMP_README.md
@@ -32,14 +32,70 @@ Das System bietet folgende STOMP-Funktionalitäten:
```javascript
// Mit SockJS
-const socket = new SockJS('http://localhost:8080/ws');
+const socket = new SockJS('http://192.168.180.196:8080/ws');
const stompClient = Stomp.over(socket);
-// Oder mit nativem WebSocket
-const socket = new WebSocket('ws://localhost:8080/websocket');
+// Oder mit nativem WebSocket (WICHTIG: ws:// verwenden, nicht http://)
+const socket = new WebSocket('ws://192.168.180.196:8080/websocket');
const stompClient = Stomp.over(socket);
```
+### Flutter/Dart STOMP Client
+
+**Für Flutter-Apps verwenden Sie diese Konfiguration:**
+
+```dart
+import 'package:stomp_dart_client/stomp.dart';
+import 'package:stomp_dart_client/stomp_config.dart';
+import 'package:stomp_dart_client/stomp_frame.dart';
+import 'dart:convert';
+
+// WICHTIG: Verwenden Sie ws:// für WebSocket-Verbindungen, NICHT http://
+final stompClient = StompClient(
+ config: StompConfig(
+ url: 'ws://192.168.180.196:8080/websocket', // Beachten Sie ws:// statt http://
+ onConnect: onConnectCallback,
+ onWebSocketError: (dynamic error) => print('WebSocket Error: $error'),
+ onStompError: (StompFrame frame) => print('Stomp Error: ${frame.body}'),
+ onDisconnect: (StompFrame frame) => print('Disconnected'),
+ // Heartbeat-Konfiguration
+ heartbeatIncoming: Duration(seconds: 20),
+ heartbeatOutgoing: Duration(seconds: 20),
+ ),
+);
+
+void onConnectCallback(StompFrame frame) {
+ print('Connected to STOMP server');
+
+ // Nachrichten abonnieren
+ stompClient.subscribe(
+ destination: '/topic/messages',
+ callback: (StompFrame frame) {
+ print('Received message: ${frame.body}');
+ },
+ );
+}
+
+// Verbindung herstellen
+stompClient.activate();
+
+// Nachricht senden
+void sendMessage(String content) {
+ stompClient.send(
+ destination: '/app/message',
+ body: jsonEncode({
+ 'content': content,
+ 'sender': 'FlutterApp',
+ }),
+ );
+}
+```
+
+**Alternative Endpunkte für Flutter:**
+Falls Probleme mit `/websocket` auftreten, versuchen Sie:
+- `ws://192.168.180.196:8080/stomp` (zusätzlicher Endpunkt)
+- `ws://192.168.180.196:8080/ws` (SockJS-Endpunkt ohne SockJS-Protokoll)
+
### 2. Verbindung herstellen
```javascript
diff --git a/flutter_websocket_test.html b/flutter_websocket_test.html
new file mode 100644
index 0000000..7f71fcd
--- /dev/null
+++ b/flutter_websocket_test.html
@@ -0,0 +1,159 @@
+
+
+
+
+
+ Flutter WebSocket Test
+
+
+
+ Flutter WebSocket STOMP Test
+ Nicht verbunden
+
+
+
+
+
+
+
+
+
+
+
+ Flutter Dart Code Beispiel:
+
+import 'package:stomp_dart_client/stomp.dart';
+import 'package:stomp_dart_client/stomp_config.dart';
+import 'package:stomp_dart_client/stomp_frame.dart';
+import 'dart:convert';
+
+// RICHTIG: ws:// für WebSocket verwenden
+final stompClient = StompClient(
+ config: StompConfig(
+ url: 'ws://192.168.180.196:8080/websocket', // ws:// NICHT http://
+ onConnect: (StompFrame frame) {
+ print('Connected to STOMP server');
+
+ // Nachrichten abonnieren
+ stompClient.subscribe(
+ destination: '/topic/messages',
+ callback: (StompFrame frame) {
+ print('Received: ${frame.body}');
+ },
+ );
+ },
+ onWebSocketError: (dynamic error) => print('WebSocket Error: $error'),
+ onStompError: (StompFrame frame) => print('Stomp Error: ${frame.body}'),
+ onDisconnect: (StompFrame frame) => print('Disconnected'),
+ ),
+);
+
+// Verbindung aktivieren
+stompClient.activate();
+
+// Nachricht senden
+void sendMessage(String content) {
+ stompClient.send(
+ destination: '/app/message',
+ body: jsonEncode({
+ 'content': content,
+ 'sender': 'FlutterApp',
+ }),
+ );
+}
+
+
+ Verfügbare Endpunkte:
+
+ - ws://192.168.180.196:8080/websocket - Native WebSocket (empfohlen für Flutter)
+ - ws://192.168.180.196:8080/stomp - Alternative WebSocket Endpunkt
+ - http://192.168.180.196:8080/ws - SockJS Endpunkt (nur für Browser)
+
+
+ Häufiger Fehler:
+ FALSCH: http://192.168.180.196:8080/websocket
+ RICHTIG: ws://192.168.180.196:8080/websocket
+
+
diff --git a/src/main/java/de/assecutor/votianlt/config/WebSocketConfig.java b/src/main/java/de/assecutor/votianlt/config/WebSocketConfig.java
index c0cc8a7..2a60a3d 100644
--- a/src/main/java/de/assecutor/votianlt/config/WebSocketConfig.java
+++ b/src/main/java/de/assecutor/votianlt/config/WebSocketConfig.java
@@ -5,6 +5,7 @@ import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
+import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
/**
* WebSocket configuration for STOMP messaging.
@@ -23,15 +24,32 @@ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
// Designate the "/app" prefix for messages that are bound to methods
// annotated with @MessageMapping
config.setApplicationDestinationPrefixes("/app");
+
+ // Set user destination prefix for user-specific messages
+ config.setUserDestinationPrefix("/user");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
- // Register the "/ws" endpoint for WebSocket connections
- // withSockJS() enables SockJS fallback options for browsers that don't support WebSocket
- registry.addEndpoint("/ws").withSockJS();
+ // Register the "/ws" endpoint for WebSocket connections with SockJS fallback
+ registry.addEndpoint("/ws")
+ .setAllowedOriginPatterns("*")
+ .addInterceptors(new HttpSessionHandshakeInterceptor())
+ .withSockJS()
+ .setHeartbeatTime(25000) // Set heartbeat interval
+ .setDisconnectDelay(5000) // Set disconnect delay
+ .setStreamBytesLimit(128 * 1024) // Set stream bytes limit
+ .setHttpMessageCacheSize(1000) // Set HTTP message cache size
+ .setSessionCookieNeeded(false); // Disable session cookie requirement
- // Also add a plain WebSocket endpoint without SockJS for native WebSocket clients
- registry.addEndpoint("/websocket");
+ // Plain WebSocket endpoint without SockJS for native WebSocket clients (Flutter, mobile apps)
+ registry.addEndpoint("/websocket")
+ .setAllowedOriginPatterns("*")
+ .addInterceptors(new HttpSessionHandshakeInterceptor());
+
+ // Additional endpoint specifically for mobile/Flutter clients that might have URL issues
+ registry.addEndpoint("/stomp")
+ .setAllowedOriginPatterns("*")
+ .addInterceptors(new HttpSessionHandshakeInterceptor());
}
}
\ No newline at end of file
diff --git a/src/main/java/de/assecutor/votianlt/security/SecurityConfig.java b/src/main/java/de/assecutor/votianlt/security/SecurityConfig.java
index 8abd6c5..2be02dd 100644
--- a/src/main/java/de/assecutor/votianlt/security/SecurityConfig.java
+++ b/src/main/java/de/assecutor/votianlt/security/SecurityConfig.java
@@ -37,10 +37,26 @@ public class SecurityConfig extends VaadinWebSecurity {
new AntPathRequestMatcher("/frontend/**"),
new AntPathRequestMatcher("/webjars/**"),
new AntPathRequestMatcher("/h2-console/**"),
- new AntPathRequestMatcher("/frontend-es5/**", "/frontend-es6/**")
+ new AntPathRequestMatcher("/frontend-es5/**", "/frontend-es6/**"),
+ // WebSocket und STOMP Endpunkte
+ new AntPathRequestMatcher("/ws/**"),
+ new AntPathRequestMatcher("/websocket/**"),
+ new AntPathRequestMatcher("/stomp/**"),
+ new AntPathRequestMatcher("/app/**"),
+ new AntPathRequestMatcher("/topic/**"),
+ new AntPathRequestMatcher("/queue/**")
).permitAll()
);
+ // CSRF für WebSocket-Endpunkte deaktivieren
+ http.csrf(csrf -> csrf
+ .ignoringRequestMatchers(
+ new AntPathRequestMatcher("/ws/**"),
+ new AntPathRequestMatcher("/websocket/**"),
+ new AntPathRequestMatcher("/stomp/**")
+ )
+ );
+
// Delegiere die Basis-Konfiguration an VaadinWebSecurity
// Dies fügt automatisch .anyRequest().authenticated() hinzu
super.configure(http);
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index fd41aae..0079313 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1,4 +1,5 @@
server.port=${PORT:8080}
+server.address=0.0.0.0
logging.level.org.atmosphere=warn
spring.mustache.check-template-location=false