feat: WebSocket temps réel + Finance Workflow + corrections
- Task #6: WebSocket /ws/dashboard + Kafka events (5 topics) * Backend: KafkaEventProducer, KafkaEventConsumer * Mobile: WebSocketService (reconnection, heartbeat, typed events) * DashboardBloc: Auto-refresh depuis WebSocket events - Finance Workflow: approbations + budgets (backend + mobile) * Backend: entities, services, resources, migrations Flyway V6 * Mobile: features finance_workflow complète avec BLoC - Corrections DI: interfaces IRepository partout * IProfileRepository, IOrganizationRepository, IMembreRepository * GetIt configuré avec @injectable - Spec-Kit: constitution + templates mis à jour * .specify/memory/constitution.md enrichie * Templates agent, plan, spec, tasks, checklist - Nettoyage: fichiers temporaires supprimés Signed-off-by: lions dev Team
This commit is contained in:
215
unionflow/scripts/kafka/GUIDE_TESTS.md
Normal file
215
unionflow/scripts/kafka/GUIDE_TESTS.md
Normal file
@@ -0,0 +1,215 @@
|
||||
# 🧪 Guide de Tests - Kafka + WebSocket UnionFlow
|
||||
|
||||
## ✅ Statut Actuel
|
||||
|
||||
Backend démarré avec succès :
|
||||
- ✅ 5 Producers Kafka connectés
|
||||
- ✅ 5 Consumers Kafka connectés (group: `unionflow-websocket-server`)
|
||||
- ✅ WebSocket endpoint actif sur `/ws/dashboard`
|
||||
- ✅ Aucune erreur `UNKNOWN_TOPIC_OR_PARTITION`
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Test 1 : Swagger UI
|
||||
|
||||
### Action
|
||||
Ouvre ton navigateur : **http://localhost:8085/q/swagger-ui**
|
||||
|
||||
### Résultat attendu
|
||||
- Page Swagger UI affichée
|
||||
- Liste de tous les endpoints REST
|
||||
- Section "Schemas" avec les DTOs
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Test 2 : WebSocket - Test HTML
|
||||
|
||||
### Action
|
||||
|
||||
1. Ouvre le fichier HTML dans ton navigateur :
|
||||
```
|
||||
C:\Users\dadyo\PersonalProjects\lions-workspace\unionflow\scripts\kafka\test-websocket.html
|
||||
```
|
||||
|
||||
2. Clique sur le bouton **"🔗 Connecter"**
|
||||
|
||||
### Résultat attendu
|
||||
|
||||
✅ **Status change vers "✅ Connecté"**
|
||||
✅ **Message dans la console** : "Connexion WebSocket établie avec succès !"
|
||||
✅ **Dans les logs backend** : Tu devrais voir :
|
||||
```
|
||||
INFO WebSocket connection opened from ...
|
||||
```
|
||||
|
||||
### Test Ping/Pong
|
||||
|
||||
1. Clique sur **"📤 Envoyer Ping"**
|
||||
2. Tu devrais recevoir un **pong** du serveur
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Test 3 : Publier un Event Kafka → Vérifier Réception WebSocket
|
||||
|
||||
### Étape 1 : Ouvrir 3 fenêtres
|
||||
|
||||
1. **Fenêtre 1** : Logs backend Quarkus (déjà ouverte)
|
||||
2. **Fenêtre 2** : Navigateur avec `test-websocket.html` (WebSocket connecté)
|
||||
3. **Fenêtre 3** : PowerShell pour publier l'event
|
||||
|
||||
### Étape 2 : Publier un Event de Test
|
||||
|
||||
Dans PowerShell (Fenêtre 3) :
|
||||
|
||||
```powershell
|
||||
cd C:\Users\dadyo\PersonalProjects\lions-workspace\unionflow\scripts\kafka
|
||||
.\test-event.bat
|
||||
```
|
||||
|
||||
**Ou manuellement** :
|
||||
|
||||
```cmd
|
||||
echo {"eventType":"APPROVAL_APPROVED","timestamp":"2026-03-14T19:30:00Z","organizationId":"test-org-123","data":{"id":"test-1","amount":50000}} | docker exec -i kafka /opt/kafka/bin/kafka-console-producer.sh --topic unionflow.finance.approvals --bootstrap-server localhost:9092
|
||||
```
|
||||
|
||||
### Résultat attendu
|
||||
|
||||
#### Dans les logs backend (Fenêtre 1) :
|
||||
```
|
||||
INFO [dev.lions.unionflow.server.messaging.KafkaEventConsumer] (smallrye-kafka-consumer-thread-1)
|
||||
Received finance approval event: key=..., value={"eventType":"APPROVAL_APPROVED",...}
|
||||
```
|
||||
|
||||
#### Dans le WebSocket HTML (Fenêtre 2) :
|
||||
```
|
||||
[19:30:15] RECEIVED: APPROVAL_APPROVED
|
||||
{
|
||||
"eventType": "APPROVAL_APPROVED",
|
||||
"timestamp": "2026-03-14T19:30:00Z",
|
||||
"organizationId": "test-org-123",
|
||||
"data": { "id": "test-1", "amount": 50000 }
|
||||
}
|
||||
```
|
||||
|
||||
✅ **Si tu vois l'event dans le WebSocket HTML → SUCCÈS COMPLET !**
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Test 4 : Vérifier les Topics Kafka
|
||||
|
||||
### Lister tous les messages d'un topic
|
||||
|
||||
```cmd
|
||||
docker exec kafka /opt/kafka/bin/kafka-console-consumer.sh --topic unionflow.finance.approvals --bootstrap-server localhost:9092 --from-beginning
|
||||
```
|
||||
|
||||
Appuie sur `Ctrl+C` pour arrêter.
|
||||
|
||||
### Compter les messages
|
||||
|
||||
```cmd
|
||||
docker exec kafka /opt/kafka/bin/kafka-run-class.sh kafka.tools.GetOffsetShell --broker-list localhost:9092 --topic unionflow.finance.approvals
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Test 5 : Application Mobile Flutter
|
||||
|
||||
### Lancer l'app mobile
|
||||
|
||||
```bash
|
||||
cd C:\Users\dadyo\PersonalProjects\lions-workspace\unionflow\unionflow-mobile-apps
|
||||
flutter run --dart-define=ENV=dev
|
||||
```
|
||||
|
||||
### Résultat attendu dans la console mobile
|
||||
|
||||
```
|
||||
I/flutter (12345): ✅ WebSocket connecté
|
||||
I/flutter (12345): DashboardBloc: WebSocket initialisé
|
||||
I/flutter (12345): DashboardBloc: WebSocket connecté - Temps réel actif
|
||||
```
|
||||
|
||||
### Test complet Mobile + Backend
|
||||
|
||||
1. **Mobile** : Ouvre le Dashboard
|
||||
2. **Backend** : Publie un event via Swagger ou Kafka console
|
||||
3. **Mobile** : Le dashboard devrait se rafraîchir automatiquement !
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Test 6 : End-to-End avec Swagger UI
|
||||
|
||||
### Scénario : Approbation Finance
|
||||
|
||||
1. **Ouvre Swagger UI** : http://localhost:8085/q/swagger-ui
|
||||
2. **Trouve l'endpoint** : `POST /api/v1/finance/approvals/{id}/approve`
|
||||
3. **Exécute la requête** avec un ID de test
|
||||
4. **Vérifie les logs backend** :
|
||||
```
|
||||
INFO KafkaEventProducer: Publishing approval event...
|
||||
INFO KafkaEventConsumer: Received finance approval event...
|
||||
INFO WebSocketBroadcastService: Broadcasting to X clients...
|
||||
```
|
||||
5. **Vérifie le WebSocket HTML** : L'event devrait apparaître !
|
||||
|
||||
---
|
||||
|
||||
## 📊 Résumé des Tests
|
||||
|
||||
| Test | Objectif | Status |
|
||||
|------|----------|--------|
|
||||
| 1. Swagger UI | Accès API REST | ⏳ À tester |
|
||||
| 2. WebSocket HTML | Connexion WebSocket | ⏳ À tester |
|
||||
| 3. Kafka → WebSocket | Flux complet | ⏳ À tester |
|
||||
| 4. Kafka Topics | Vérification messages | ⏳ À tester |
|
||||
| 5. Mobile Flutter | WebSocket mobile | ⏳ À tester |
|
||||
| 6. End-to-End Swagger | Workflow complet | ⏳ À tester |
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### WebSocket ne se connecte pas
|
||||
|
||||
**Vérifier** :
|
||||
```cmd
|
||||
netstat -an | findstr 8085
|
||||
```
|
||||
|
||||
Doit afficher : `0.0.0.0:8085 ... LISTENING`
|
||||
|
||||
### Events Kafka non reçus
|
||||
|
||||
**Vérifier les consumers** :
|
||||
```cmd
|
||||
docker exec kafka /opt/kafka/bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group unionflow-websocket-server
|
||||
```
|
||||
|
||||
Doit afficher :
|
||||
- LAG = 0 (tous les messages consommés)
|
||||
- 5 topics assignés au group
|
||||
|
||||
### Backend logs
|
||||
|
||||
**Augmenter le niveau de log** dans `application.properties` :
|
||||
```properties
|
||||
quarkus.log.category."dev.lions.unionflow.server.messaging".level=DEBUG
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Succès Final
|
||||
|
||||
Quand tous ces tests passent :
|
||||
- ✅ Backend publie events dans Kafka
|
||||
- ✅ Consumers consomment events
|
||||
- ✅ WebSocket broadcast aux clients
|
||||
- ✅ Mobile reçoit events en temps réel
|
||||
- ✅ Dashboard auto-refresh
|
||||
|
||||
**→ Architecture Event-Driven 100% FONCTIONNELLE ! 🎉**
|
||||
|
||||
---
|
||||
|
||||
**Commence par le Test 2 (WebSocket HTML)** - c'est le plus visuel et le plus rapide pour vérifier que tout fonctionne !
|
||||
155
unionflow/scripts/kafka/README.md
Normal file
155
unionflow/scripts/kafka/README.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# Scripts Kafka pour UnionFlow
|
||||
|
||||
## Problème résolu
|
||||
|
||||
Les erreurs `UNKNOWN_TOPIC_OR_PARTITION` apparaissent car **les topics Kafka n'existent pas encore**.
|
||||
|
||||
Ton Kafka actuel (conteneur `kafka` sur port 9092) fonctionne parfaitement. Il faut juste créer les 5 topics.
|
||||
|
||||
---
|
||||
|
||||
## ✅ Solution : Créer les Topics
|
||||
|
||||
### Option 1 : Exécuter le script (Recommandé)
|
||||
|
||||
#### Windows (PowerShell ou CMD)
|
||||
|
||||
```cmd
|
||||
cd C:\Users\dadyo\PersonalProjects\lions-workspace\unionflow\scripts\kafka
|
||||
create-topics.bat
|
||||
```
|
||||
|
||||
#### Linux/Mac
|
||||
|
||||
```bash
|
||||
cd /path/to/unionflow/scripts/kafka
|
||||
chmod +x create-topics.sh
|
||||
./create-topics.sh
|
||||
```
|
||||
|
||||
### Option 2 : Commandes manuelles (si le script échoue)
|
||||
|
||||
Copie-colle ces commandes une par une dans PowerShell/CMD :
|
||||
|
||||
```cmd
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --create --topic unionflow.finance.approvals --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1 --if-not-exists
|
||||
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --create --topic unionflow.dashboard.stats --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1 --if-not-exists
|
||||
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --create --topic unionflow.notifications.user --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1 --if-not-exists
|
||||
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --create --topic unionflow.members.events --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1 --if-not-exists
|
||||
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --create --topic unionflow.contributions.events --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1 --if-not-exists
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Vérification des Topics
|
||||
|
||||
### Lister tous les topics
|
||||
|
||||
```cmd
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --list --bootstrap-server localhost:9092
|
||||
```
|
||||
|
||||
Résultat attendu :
|
||||
```
|
||||
unionflow.contributions.events
|
||||
unionflow.dashboard.stats
|
||||
unionflow.finance.approvals
|
||||
unionflow.members.events
|
||||
unionflow.notifications.user
|
||||
```
|
||||
|
||||
### Voir les détails d'un topic
|
||||
|
||||
```cmd
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --describe --topic unionflow.finance.approvals --bootstrap-server localhost:9092
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Topics Créés
|
||||
|
||||
| Topic | Partitions | Replication | Usage |
|
||||
|-------|------------|-------------|-------|
|
||||
| `unionflow.finance.approvals` | 3 | 1 | Workflow approbations financières |
|
||||
| `unionflow.dashboard.stats` | 3 | 1 | Mise à jour stats dashboard |
|
||||
| `unionflow.notifications.user` | 3 | 1 | Notifications utilisateurs |
|
||||
| `unionflow.members.events` | 3 | 1 | Events création/modification membres |
|
||||
| `unionflow.contributions.events` | 3 | 1 | Events paiements cotisations |
|
||||
|
||||
**Partitions** : 3 pour parallélisme (peut augmenter en prod si besoin)
|
||||
**Replication** : 1 (développement single-node)
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Tester la Configuration
|
||||
|
||||
### 1. Publier un message de test
|
||||
|
||||
```cmd
|
||||
docker exec -it kafka /opt/kafka/bin/kafka-console-producer.sh --topic unionflow.finance.approvals --bootstrap-server localhost:9092
|
||||
```
|
||||
|
||||
Tape un message JSON et appuie sur Entrée :
|
||||
```json
|
||||
{"eventType":"TEST","timestamp":"2026-03-14T19:00:00Z","data":{"message":"test"}}
|
||||
```
|
||||
|
||||
Ctrl+C pour quitter.
|
||||
|
||||
### 2. Consommer les messages
|
||||
|
||||
```cmd
|
||||
docker exec -it kafka /opt/kafka/bin/kafka-console-consumer.sh --topic unionflow.finance.approvals --bootstrap-server localhost:9092 --from-beginning
|
||||
```
|
||||
|
||||
Tu devrais voir le message de test. Ctrl+C pour quitter.
|
||||
|
||||
---
|
||||
|
||||
## ✅ Résultat Attendu
|
||||
|
||||
Après création des topics, redémarre le backend Quarkus :
|
||||
|
||||
```bash
|
||||
cd unionflow-server-impl-quarkus
|
||||
./mvnw quarkus:dev
|
||||
```
|
||||
|
||||
Les erreurs `UNKNOWN_TOPIC_OR_PARTITION` **disparaîtront** et tu verras :
|
||||
|
||||
```
|
||||
✅ Kafka consumers started successfully
|
||||
✅ Connected to topics: unionflow.finance.approvals, unionflow.dashboard.stats, ...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ❓ FAQ
|
||||
|
||||
### Puis-je supprimer mon Kafka actuel ?
|
||||
|
||||
**NON !** Ton Kafka actuel est parfait. Garde-le. Il manque juste les topics.
|
||||
|
||||
### Dois-je utiliser docker-compose ?
|
||||
|
||||
Non, ton setup actuel (conteneur `kafka` standalone) fonctionne très bien pour le développement.
|
||||
|
||||
### En production ?
|
||||
|
||||
En production (Kubernetes), les topics seront créés automatiquement par le backend au démarrage (via `auto.create.topics.enable=true` dans Kafka) ou via Helm charts.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Après Création des Topics
|
||||
|
||||
1. **Redémarrer backend Quarkus** : `./mvnw quarkus:dev`
|
||||
2. **Lancer mobile** : `flutter run --dart-define=ENV=dev`
|
||||
3. **Tester WebSocket** : Publier un event via Swagger UI → vérifier réception mobile
|
||||
|
||||
---
|
||||
|
||||
**Status** : ✅ Topics créés → Backend connecté → WebSocket fonctionnel
|
||||
39
unionflow/scripts/kafka/create-topics.bat
Normal file
39
unionflow/scripts/kafka/create-topics.bat
Normal file
@@ -0,0 +1,39 @@
|
||||
@echo off
|
||||
REM Script pour créer les topics Kafka pour UnionFlow
|
||||
REM Exécuter depuis le répertoire unionflow/
|
||||
|
||||
echo ====================================
|
||||
echo Création des topics Kafka UnionFlow
|
||||
echo ====================================
|
||||
echo.
|
||||
|
||||
echo Topic 1/5: unionflow.finance.approvals
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --create --topic unionflow.finance.approvals --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1 --if-not-exists
|
||||
|
||||
echo Topic 2/5: unionflow.dashboard.stats
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --create --topic unionflow.dashboard.stats --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1 --if-not-exists
|
||||
|
||||
echo Topic 3/5: unionflow.notifications.user
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --create --topic unionflow.notifications.user --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1 --if-not-exists
|
||||
|
||||
echo Topic 4/5: unionflow.members.events
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --create --topic unionflow.members.events --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1 --if-not-exists
|
||||
|
||||
echo Topic 5/5: unionflow.contributions.events
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --create --topic unionflow.contributions.events --bootstrap-server localhost:9092 --partitions 3 --replication-factor 1 --if-not-exists
|
||||
|
||||
echo.
|
||||
echo ====================================
|
||||
echo Vérification des topics créés
|
||||
echo ====================================
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --list --bootstrap-server localhost:9092
|
||||
|
||||
echo.
|
||||
echo ====================================
|
||||
echo Détails des topics UnionFlow
|
||||
echo ====================================
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --describe --bootstrap-server localhost:9092 | findstr unionflow
|
||||
|
||||
echo.
|
||||
echo ✅ Topics Kafka créés avec succès !
|
||||
pause
|
||||
62
unionflow/scripts/kafka/create-topics.sh
Normal file
62
unionflow/scripts/kafka/create-topics.sh
Normal file
@@ -0,0 +1,62 @@
|
||||
#!/bin/bash
|
||||
# Script pour créer les topics Kafka pour UnionFlow
|
||||
|
||||
echo "===================================="
|
||||
echo "Création des topics Kafka UnionFlow"
|
||||
echo "===================================="
|
||||
echo ""
|
||||
|
||||
echo "Topic 1/5: unionflow.finance.approvals"
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --create \
|
||||
--topic unionflow.finance.approvals \
|
||||
--bootstrap-server localhost:9092 \
|
||||
--partitions 3 \
|
||||
--replication-factor 1 \
|
||||
--if-not-exists
|
||||
|
||||
echo "Topic 2/5: unionflow.dashboard.stats"
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --create \
|
||||
--topic unionflow.dashboard.stats \
|
||||
--bootstrap-server localhost:9092 \
|
||||
--partitions 3 \
|
||||
--replication-factor 1 \
|
||||
--if-not-exists
|
||||
|
||||
echo "Topic 3/5: unionflow.notifications.user"
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --create \
|
||||
--topic unionflow.notifications.user \
|
||||
--bootstrap-server localhost:9092 \
|
||||
--partitions 3 \
|
||||
--replication-factor 1 \
|
||||
--if-not-exists
|
||||
|
||||
echo "Topic 4/5: unionflow.members.events"
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --create \
|
||||
--topic unionflow.members.events \
|
||||
--bootstrap-server localhost:9092 \
|
||||
--partitions 3 \
|
||||
--replication-factor 1 \
|
||||
--if-not-exists
|
||||
|
||||
echo "Topic 5/5: unionflow.contributions.events"
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --create \
|
||||
--topic unionflow.contributions.events \
|
||||
--bootstrap-server localhost:9092 \
|
||||
--partitions 3 \
|
||||
--replication-factor 1 \
|
||||
--if-not-exists
|
||||
|
||||
echo ""
|
||||
echo "===================================="
|
||||
echo "Vérification des topics créés"
|
||||
echo "===================================="
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --list --bootstrap-server localhost:9092
|
||||
|
||||
echo ""
|
||||
echo "===================================="
|
||||
echo "Détails des topics UnionFlow"
|
||||
echo "===================================="
|
||||
docker exec kafka /opt/kafka/bin/kafka-topics.sh --describe --bootstrap-server localhost:9092 | grep unionflow
|
||||
|
||||
echo ""
|
||||
echo "✅ Topics Kafka créés avec succès !"
|
||||
31
unionflow/scripts/kafka/test-event.bat
Normal file
31
unionflow/scripts/kafka/test-event.bat
Normal file
@@ -0,0 +1,31 @@
|
||||
@echo off
|
||||
REM Script pour tester la publication et consommation d'events Kafka
|
||||
|
||||
echo ====================================
|
||||
echo Test Event Kafka - UnionFlow
|
||||
echo ====================================
|
||||
echo.
|
||||
|
||||
echo 📤 Publication d'un event de test dans unionflow.finance.approvals...
|
||||
echo.
|
||||
|
||||
REM Créer un fichier temporaire avec l'event JSON
|
||||
echo {"eventType":"APPROVAL_APPROVED","timestamp":"2026-03-14T19:30:00Z","organizationId":"test-org-123","data":{"id":"test-approval-1","transactionType":"COTISATION","amount":50000,"currency":"XOF","approvedBy":"admin@test.com","approvedAt":"2026-03-14T19:30:00Z"}} > %TEMP%\kafka-test-event.json
|
||||
|
||||
REM Publier l'event dans Kafka
|
||||
docker exec -i kafka /opt/kafka/bin/kafka-console-producer.sh --topic unionflow.finance.approvals --bootstrap-server localhost:9092 < %TEMP%\kafka-test-event.json
|
||||
|
||||
echo.
|
||||
echo ✅ Event publié dans unionflow.finance.approvals
|
||||
echo.
|
||||
echo 📥 Pour consommer les events (dans une autre fenêtre CMD) :
|
||||
echo docker exec -it kafka /opt/kafka/bin/kafka-console-consumer.sh --topic unionflow.finance.approvals --bootstrap-server localhost:9092 --from-beginning
|
||||
echo.
|
||||
echo 📊 Vérifie les logs du backend Quarkus :
|
||||
echo Tu devrais voir : "Received finance approval event"
|
||||
echo.
|
||||
|
||||
REM Nettoyer
|
||||
del %TEMP%\kafka-test-event.json
|
||||
|
||||
pause
|
||||
226
unionflow/scripts/kafka/test-websocket.html
Normal file
226
unionflow/scripts/kafka/test-websocket.html
Normal file
@@ -0,0 +1,226 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Test WebSocket UnionFlow</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.container {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
h1 {
|
||||
color: #2c3e50;
|
||||
border-bottom: 3px solid #3498db;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.status {
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
margin: 10px 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
.connected {
|
||||
background-color: #d4edda;
|
||||
color: #155724;
|
||||
border: 1px solid #c3e6cb;
|
||||
}
|
||||
.disconnected {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
border: 1px solid #f5c6cb;
|
||||
}
|
||||
button {
|
||||
background-color: #3498db;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
margin: 5px;
|
||||
font-size: 14px;
|
||||
}
|
||||
button:hover {
|
||||
background-color: #2980b9;
|
||||
}
|
||||
button:disabled {
|
||||
background-color: #95a5a6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
#messages {
|
||||
background-color: #2c3e50;
|
||||
color: #ecf0f1;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
height: 400px;
|
||||
overflow-y: auto;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 12px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.event {
|
||||
margin: 5px 0;
|
||||
padding: 8px;
|
||||
border-left: 3px solid #3498db;
|
||||
background-color: #34495e;
|
||||
}
|
||||
.event-type {
|
||||
color: #3498db;
|
||||
font-weight: bold;
|
||||
}
|
||||
.timestamp {
|
||||
color: #95a5a6;
|
||||
font-size: 11px;
|
||||
}
|
||||
.controls {
|
||||
margin: 20px 0;
|
||||
}
|
||||
.info {
|
||||
background-color: #d1ecf1;
|
||||
border: 1px solid #bee5eb;
|
||||
color: #0c5460;
|
||||
padding: 12px;
|
||||
border-radius: 4px;
|
||||
margin: 15px 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>🔌 Test WebSocket UnionFlow</h1>
|
||||
|
||||
<div class="info">
|
||||
<strong>URL WebSocket :</strong> ws://localhost:8085/ws/dashboard
|
||||
</div>
|
||||
|
||||
<div id="status" class="status disconnected">
|
||||
❌ Déconnecté
|
||||
</div>
|
||||
|
||||
<div class="controls">
|
||||
<button id="connectBtn" onclick="connect()">🔗 Connecter</button>
|
||||
<button id="disconnectBtn" onclick="disconnect()" disabled>🔌 Déconnecter</button>
|
||||
<button id="pingBtn" onclick="sendPing()" disabled>📤 Envoyer Ping</button>
|
||||
<button id="clearBtn" onclick="clearMessages()">🗑️ Effacer</button>
|
||||
</div>
|
||||
|
||||
<h3>📨 Messages reçus :</h3>
|
||||
<div id="messages"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let ws = null;
|
||||
let reconnectInterval = null;
|
||||
|
||||
function updateStatus(connected) {
|
||||
const statusDiv = document.getElementById('status');
|
||||
const connectBtn = document.getElementById('connectBtn');
|
||||
const disconnectBtn = document.getElementById('disconnectBtn');
|
||||
const pingBtn = document.getElementById('pingBtn');
|
||||
|
||||
if (connected) {
|
||||
statusDiv.className = 'status connected';
|
||||
statusDiv.innerHTML = '✅ Connecté';
|
||||
connectBtn.disabled = true;
|
||||
disconnectBtn.disabled = false;
|
||||
pingBtn.disabled = false;
|
||||
} else {
|
||||
statusDiv.className = 'status disconnected';
|
||||
statusDiv.innerHTML = '❌ Déconnecté';
|
||||
connectBtn.disabled = false;
|
||||
disconnectBtn.disabled = true;
|
||||
pingBtn.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
function addMessage(type, message, data = null) {
|
||||
const messagesDiv = document.getElementById('messages');
|
||||
const timestamp = new Date().toLocaleTimeString('fr-FR');
|
||||
|
||||
let content = `<div class="event">`;
|
||||
content += `<span class="timestamp">[${timestamp}]</span> `;
|
||||
content += `<span class="event-type">${type}</span>: ${message}`;
|
||||
|
||||
if (data) {
|
||||
content += `<pre style="margin: 5px 0; padding: 5px; background: #1a252f; border-radius: 3px;">${JSON.stringify(data, null, 2)}</pre>`;
|
||||
}
|
||||
|
||||
content += `</div>`;
|
||||
|
||||
messagesDiv.innerHTML += content;
|
||||
messagesDiv.scrollTop = messagesDiv.scrollHeight;
|
||||
}
|
||||
|
||||
function connect() {
|
||||
try {
|
||||
addMessage('SYSTEM', 'Tentative de connexion à ws://localhost:8085/ws/dashboard...');
|
||||
|
||||
ws = new WebSocket('ws://localhost:8085/ws/dashboard');
|
||||
|
||||
ws.onopen = function() {
|
||||
updateStatus(true);
|
||||
addMessage('SYSTEM', '✅ Connexion WebSocket établie avec succès !');
|
||||
};
|
||||
|
||||
ws.onmessage = function(event) {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
const eventType = data.type || data.eventType || 'UNKNOWN';
|
||||
addMessage('RECEIVED', eventType, data);
|
||||
} catch (e) {
|
||||
addMessage('RECEIVED', 'Message brut', event.data);
|
||||
}
|
||||
};
|
||||
|
||||
ws.onerror = function(error) {
|
||||
addMessage('ERROR', 'Erreur WebSocket', error);
|
||||
};
|
||||
|
||||
ws.onclose = function() {
|
||||
updateStatus(false);
|
||||
addMessage('SYSTEM', '❌ Connexion WebSocket fermée');
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
addMessage('ERROR', 'Erreur lors de la connexion', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
if (ws) {
|
||||
ws.close();
|
||||
ws = null;
|
||||
updateStatus(false);
|
||||
addMessage('SYSTEM', 'Déconnexion manuelle');
|
||||
}
|
||||
}
|
||||
|
||||
function sendPing() {
|
||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||
const ping = { type: 'ping' };
|
||||
ws.send(JSON.stringify(ping));
|
||||
addMessage('SENT', 'Ping envoyé', ping);
|
||||
}
|
||||
}
|
||||
|
||||
function clearMessages() {
|
||||
document.getElementById('messages').innerHTML = '';
|
||||
addMessage('SYSTEM', 'Messages effacés');
|
||||
}
|
||||
|
||||
// Auto-connect au chargement
|
||||
window.onload = function() {
|
||||
addMessage('SYSTEM', 'Page chargée. Prêt à se connecter.');
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user