Hibernate validate mode in prod requires exact table names. V1 used singular names (permission, document, suggestion, etc.) but entities use plural names (permissions, documents, suggestions, etc.). Hibernate update mode was masking this by auto-creating plural tables. Renamed 23 tables to match entities.
UnionFlow Backend - API REST Quarkus
Backend REST API pour UnionFlow - Gestion des mutuelles, associations et organisations Lions Club.
📋 Table des Matières
- Architecture
- Technologies
- Prérequis
- Installation
- Configuration
- Lancement
- API Documentation
- Base de données
- Kafka Event Streaming
- WebSocket Temps Réel
- Tests
- Déploiement
🏗️ Architecture
Clean Architecture + DDD
src/main/java/dev/lions/unionflow/
├── domain/ # Domain Layer (Entities métier)
│ ├── entities/ # Entités JPA (37 entités)
│ └── repositories/ # Repositories Panache
├── application/ # Application Layer (Use Cases)
│ └── services/ # Services métier
├── infrastructure/ # Infrastructure Layer
│ ├── rest/ # REST Controllers
│ ├── messaging/ # Kafka Producers
│ ├── websocket/ # WebSocket endpoints
│ └── persistence/ # Configuration JPA
└── shared/ # Shared Kernel
├── dto/ # DTOs (Request/Response)
├── exceptions/ # Custom exceptions
└── mappers/ # MapStruct mappers
Pattern Repository avec Panache
Tous les repositories étendent PanacheRepositoryBase<Entity, UUID> pour :
- CRUD automatique
- Queries typées
- Streaming support
- Active Record pattern (optionnel)
🛠️ Technologies
| Composant | Version | Usage |
|---|---|---|
| Java | 17 (LTS) | Langage |
| Quarkus | 3.15.1 | Framework application |
| Hibernate ORM (Panache) | 6.4+ | Persistence |
| PostgreSQL | 15 | Base de données |
| Flyway | 9.22+ | Migrations DB |
| Kafka | SmallRye Reactive Messaging | Event streaming |
| WebSocket | Quarkus WebSockets Next | Temps réel |
| Keycloak | OIDC/JWT | Authentification |
| OpenPDF | 1.3.30 | Export PDF |
| MapStruct | 1.5+ | Mapping DTO ↔ Entity |
| Lombok | 1.18.34 | Réduction boilerplate |
| RESTEasy | Reactive | REST endpoints |
| SmallRye Health | - | Health checks |
| SmallRye OpenAPI | - | Documentation API |
📦 Prérequis
Environnement de développement
- Java Development Kit: OpenJDK 17 ou supérieur
- Maven: 3.8+
- Docker: 20.10+ (pour PostgreSQL, Keycloak, Kafka)
- Git: 2.30+
Services externes (via Docker Compose)
cd unionflow/
docker-compose up -d
Services démarrés :
- PostgreSQL :
localhost:5432(DB:unionflow, user:unionflow, pass:unionflow) - Keycloak :
localhost:8180(realm:unionflow, client:unionflow-mobile) - Kafka :
localhost:9092(topics auto-créés) - Zookeeper :
localhost:2181 - MailDev :
localhost:1080(SMTP testing)
🚀 Installation
1. Cloner le projet
git clone https://git.lions.dev/lionsdev/unionflow-server-impl-quarkus.git
cd unionflow-server-impl-quarkus
2. Configurer Maven
Ajouter le repository Gitea à ~/.m2/settings.xml :
<settings>
<servers>
<server>
<id>gitea-lionsdev</id>
<username>${env.GITEA_USERNAME}</username>
<password>${env.GITEA_TOKEN}</password>
</server>
</servers>
<mirrors>
<mirror>
<id>gitea-maven</id>
<mirrorOf>external:*</mirrorOf>
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
</mirror>
</mirrors>
</settings>
3. Compiler
# Compilation standard
./mvnw clean package
# Sans tests (rapide)
./mvnw clean package -DskipTests
# Avec profil production
./mvnw clean package -Pproduction
⚙️ Configuration
Variables d'environnement
Développement
# Base de données
export DB_URL=jdbc:postgresql://localhost:5432/unionflow
export DB_USERNAME=unionflow
export DB_PASSWORD=unionflow
# Keycloak
export KEYCLOAK_URL=http://localhost:8180/realms/unionflow
export KEYCLOAK_CLIENT_SECRET=votre-secret-dev
# Kafka
export KAFKA_BOOTSTRAP_SERVERS=localhost:9092
Production
# Base de données
export DB_URL=jdbc:postgresql://postgresql-service.postgresql.svc.cluster.local:5432/unionflow
export DB_USERNAME=unionflow
export DB_PASSWORD=${SECURE_DB_PASSWORD}
# Keycloak
export KEYCLOAK_URL=https://security.lions.dev/realms/unionflow
export KEYCLOAK_CLIENT_SECRET=${SECURE_CLIENT_SECRET}
# Kafka
export KAFKA_BOOTSTRAP_SERVERS=kafka-service.kafka.svc.cluster.local:9092
# CORS
export CORS_ORIGINS=https://unionflow.lions.dev,https://api.lions.dev
application.properties
Dev : src/main/resources/application.properties
Prod : src/main/resources/application-prod.properties
Propriétés clés :
# HTTP
quarkus.http.port=8085
quarkus.http.cors.origins=http://localhost:3000,http://localhost:8086
# Database
quarkus.datasource.db-kind=postgresql
quarkus.hibernate-orm.database.generation=validate # Production
quarkus.flyway.migrate-at-start=true
# Keycloak OIDC
quarkus.oidc.auth-server-url=${KEYCLOAK_URL}
quarkus.oidc.client-id=unionflow-backend
quarkus.oidc.credentials.secret=${KEYCLOAK_CLIENT_SECRET}
# Kafka
kafka.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVERS:localhost:9092}
mp.messaging.outgoing.finance-approvals.connector=smallrye-kafka
# WebSocket
quarkus.websockets.enabled=true
🏃 Lancement
Mode développement (Live Reload)
./mvnw quarkus:dev
# Accès
# - API: http://localhost:8085
# - Swagger UI: http://localhost:8085/q/swagger-ui
# - Health: http://localhost:8085/q/health
# - Dev UI: http://localhost:8085/q/dev
Mode production
# Build
./mvnw clean package -Pproduction
# Run
java -jar target/quarkus-app/quarkus-run.jar
# Ou avec profil spécifique
java -Dquarkus.profile=prod -jar target/quarkus-app/quarkus-run.jar
Docker
# Build image
docker build -f src/main/docker/Dockerfile.jvm -t unionflow-backend:latest .
# Run container
docker run -p 8085:8085 \
-e DB_URL=jdbc:postgresql://host.docker.internal:5432/unionflow \
-e DB_USERNAME=unionflow \
-e DB_PASSWORD=unionflow \
-e KEYCLOAK_CLIENT_SECRET=secret \
unionflow-backend:latest
📚 API Documentation
Swagger UI
Dev : http://localhost:8085/q/swagger-ui Prod : https://api.lions.dev/unionflow/q/swagger-ui
Endpoints principaux
Finance Workflow
GET /api/v1/finance/approvals- Liste des approbations en attentePOST /api/v1/finance/approvals/{id}/approve- Approuver transactionPOST /api/v1/finance/approvals/{id}/reject- Rejeter transactionGET /api/v1/finance/budgets- Liste des budgetsPOST /api/v1/finance/budgets- Créer budget
Dashboard
GET /api/v1/dashboard/stats- Stats organisationGET /api/v1/dashboard/kpi- KPI temps réelGET /api/v1/dashboard/activities- Activités récentes
Membres
GET /api/v1/membres- Liste membresGET /api/v1/membres/{id}- Détails membrePOST /api/v1/membres- Créer membrePUT /api/v1/membres/{id}- Modifier membre
Cotisations
GET /api/v1/cotisations- Liste cotisationsPOST /api/v1/cotisations- Enregistrer cotisationGET /api/v1/cotisations/member/{memberId}- Cotisations d'un membre
Notifications
GET /api/v1/notifications- Liste notifications userPUT /api/v1/notifications/{id}/read- Marquer comme lue
🗄️ Base de données
Schéma - 37 Entités
Entités principales :
BaseEntity(classe abstraite) : id (UUID), dateCreation, dateModification, actif, versionOrganisation: nom, type, quotaMembre: nom, prenom, email, telephone, organisationCotisation: membre, montant, periode, statutAdhesion: membre, type, dateDebut, dateFinEvenement: titre, date, lieu, organisationDemandeAide: membre, categorie, montant, statutTransactionApproval: type, montant, statut (PENDING/APPROVED/REJECTED)Budget: nom, periode, année, lignes budgétairesNotification: user, titre, message, lu
Migrations Flyway
Localisation : src/main/resources/db/migration/
V1.0__Initial_Schema.sql- Création tables initialesV2.0__Finance_Workflow.sql- Tables Finance WorkflowV2.1__Add_Indexes.sql- Index performanceV3.0__Kafka_Events.sql- Support event sourcing (futur)
Exécution migrations
# Automatique au démarrage (quarkus.flyway.migrate-at-start=true)
./mvnw quarkus:dev
# Ou manuellement
./mvnw flyway:migrate
Commandes utiles
# Info migrations
./mvnw flyway:info
# Repair (en cas d'erreur)
./mvnw flyway:repair
# Baseline (migration existante DB)
./mvnw flyway:baseline
📡 Kafka Event Streaming
Topics configurés
unionflow.finance.approvals- Workflow approbationsunionflow.dashboard.stats- Stats dashboardunionflow.notifications.user- Notifications utilisateursunionflow.members.events- Événements membresunionflow.contributions.events- Cotisations
Producer Kafka
Classe : KafkaEventProducer
@ApplicationScoped
public class KafkaEventProducer {
@Channel("finance-approvals")
Emitter<String> financeEmitter;
public void publishApprovalPending(TransactionApproval approval) {
var event = Map.of(
"eventType", "APPROVAL_PENDING",
"timestamp", Instant.now().toString(),
"approval", toDTO(approval)
);
financeEmitter.send(toJson(event));
}
}
Voir KAFKA_WEBSOCKET_ARCHITECTURE.md pour l'architecture complète.
🔌 WebSocket Temps Réel
Endpoint
URL : ws://localhost:8085/ws/dashboard
Classe WebSocket
Fichier : DashboardWebSocket.java
@ServerEndpoint("/ws/dashboard")
@ApplicationScoped
public class DashboardWebSocket {
@OnOpen
public void onOpen(Session session) {
sessions.add(session);
}
@Incoming("finance-approvals")
public void handleFinanceEvent(String event) {
broadcast(event); // Broadcast à tous les clients connectés
}
}
Connexion mobile (Flutter) :
final channel = WebSocketChannel.connect(
Uri.parse('ws://localhost:8085/ws/dashboard')
);
channel.stream.listen((message) {
print('Event received: $message');
});
🧪 Tests
Lancer les tests
# Tous les tests
./mvnw test
# Tests unitaires seulement
./mvnw test -Dtest="*Test"
# Tests d'intégration seulement
./mvnw test -Dtest="*IT"
# Avec couverture
./mvnw test jacoco:report
Structure tests
src/test/java/
├── domain/
│ └── entities/
│ └── MembreTest.java
├── application/
│ └── services/
│ └── FinanceWorkflowServiceTest.java
└── infrastructure/
└── rest/
└── FinanceResourceIT.java
🚢 Déploiement
Kubernetes (Production)
Outil : lionsctl (CLI Go custom)
# Déploiement complet
lionsctl pipeline \
-u https://git.lions.dev/lionsdev/unionflow-server-impl-quarkus \
-b main \
-j 17 \
-e production \
-c k1 \
-p prod
# Étapes :
# 1. Clone repo Git
# 2. mvn clean package -Pprod
# 3. docker build + push registry.lions.dev
# 4. kubectl apply -f k8s/
# 5. Health check
# 6. Email notification
Fichiers Kubernetes
Localisation : src/main/kubernetes/
deployment.yaml- Deployment (3 replicas)service.yaml- Service ClusterIPingress.yaml- Ingress HTTPSconfigmap.yaml- Configurationsecret.yaml- Secrets (DB, Keycloak)
Accès production
- API : https://api.lions.dev/unionflow
- Swagger : https://api.lions.dev/unionflow/q/swagger-ui
- Health : https://api.lions.dev/unionflow/q/health
🔒 Sécurité
Authentification
- Méthode : OIDC/JWT via Keycloak
- Rôles : SUPER_ADMIN, ADMIN_ENTITE, MEMBRE_ACTIF, MEMBRE
- Token : Bearer token dans header
Authorization
Endpoints protégés
@RolesAllowed({"SUPER_ADMIN", "ADMIN_ENTITE"})
@POST
@Path("/budgets")
public Response createBudget(BudgetRequest request) {
// ...
}
CORS
Production : CORS configuré pour https://unionflow.lions.dev
📊 Monitoring
Health Checks
- Liveness :
GET /q/health/live - Readiness :
GET /q/health/ready
Metrics (Prometheus-compatible)
- Endpoint :
GET /q/metrics
Logs structurés
Logger.info("Finance approval created",
kv("approvalId", approval.getId()),
kv("organizationId", orgId),
kv("amount", amount)
);
📝 Contribution
- Fork le projet
- Créer une branche feature (
git checkout -b feature/AmazingFeature) - Commit changes (
git commit -m 'Add AmazingFeature') - Push to branch (
git push origin feature/AmazingFeature) - Ouvrir une Pull Request
📄 Licence
Propriétaire - © 2026 Lions Club Côte d'Ivoire - Tous droits réservés
📞 Support
- Email : support@lions.dev
- Issue Tracker : https://git.lions.dev/lionsdev/unionflow-server-impl-quarkus/issues
Version : 2.0.0 Dernière mise à jour : 2026-03-14 Auteur : Équipe UnionFlow