Files
lionsdev-client-impl-quarkus/src/main/java/dev/lions/services/WebSocketService.java

209 lines
5.9 KiB
Java

package dev.lions.services;
import dev.lions.dtos.NotificationDTO;
import dev.lions.exceptions.WebSocketException;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* Service gérant les communications WebSocket de l'application.
* Cette classe assure la gestion des connexions temps réel et la diffusion
* des notifications aux clients connectés.
*/
@Slf4j
@ApplicationScoped
@ServerEndpoint("/ws/notifications")
public class WebSocketService {
private static final Map<String, Session> sessions = new ConcurrentHashMap<>();
private static final int MAX_MESSAGE_SIZE = 8192;
private static final long IDLE_TIMEOUT = 300000; // 5 minutes
/**
* Gère l'ouverture d'une nouvelle connexion WebSocket.
*
* @param session Session WebSocket ouverte
*/
@OnOpen
public void onOpen(Session session) {
log.info("Nouvelle connexion WebSocket établie : {}", session.getId());
try {
configureSession(session);
sessions.put(session.getId(), session);
sendWelcomeMessage(session);
} catch (Exception e) {
log.error("Erreur lors de l'initialisation de la session WebSocket", e);
closeSession(session, "Erreur d'initialisation");
}
}
/**
* Configure une nouvelle session WebSocket.
*/
private void configureSession(Session session) {
session.setMaxIdleTimeout(IDLE_TIMEOUT);
session.setMaxTextMessageBufferSize(MAX_MESSAGE_SIZE);
session.setMaxBinaryMessageBufferSize(MAX_MESSAGE_SIZE);
}
/**
* Envoie un message de bienvenue au client connecté.
*/
private void sendWelcomeMessage(Session session) {
try {
String message = "{\"type\":\"welcome\",\"message\":\"Connexion établie\"}";
session.getBasicRemote().sendText(message);
} catch (Exception e) {
log.warn("Impossible d'envoyer le message de bienvenue", e);
}
}
/**
* Gère la réception d'un message depuis un client.
*
* @param message Message reçu
* @param session Session WebSocket active
*/
@OnMessage
public void onMessage(String message, Session session) {
String sessionId = session.getId();
log.debug("Message reçu de la session {} : {}", sessionId, message);
try {
validateMessage(message);
processMessage(message, session);
} catch (Exception e) {
log.error("Erreur lors du traitement du message", e);
sendErrorResponse(session, "Erreur de traitement du message");
}
}
/**
* Valide le contenu d'un message reçu.
*/
private void validateMessage(String message) {
if (message == null || message.trim().isEmpty()) {
throw new WebSocketException("Message vide non autorisé");
}
if (message.length() > MAX_MESSAGE_SIZE) {
throw new WebSocketException("Message trop long");
}
}
/**
* Traite un message reçu.
*/
private void processMessage(String message, Session session) {
// Implémentation du traitement des messages selon les besoins
log.debug("Traitement du message de la session {}", session.getId());
}
/**
* Gère la fermeture d'une connexion WebSocket.
*
* @param session Session WebSocket fermée
*/
@OnClose
public void onClose(Session session) {
String sessionId = session.getId();
log.info("Fermeture de la connexion WebSocket : {}", sessionId);
sessions.remove(sessionId);
cleanupSession(session);
}
/**
* Gère les erreurs survenant sur une connexion WebSocket.
*
* @param session Session WebSocket concernée
* @param throwable Erreur survenue
*/
@OnError
public void onError(Session session, Throwable throwable) {
String sessionId = session.getId();
log.error("Erreur WebSocket sur la session {} : {}",
sessionId, throwable.getMessage(), throwable);
closeSession(session, "Erreur interne");
}
/**
* Diffuse une notification à tous les clients connectés.
*
* @param notification Notification à diffuser
*/
public void broadcastToAdmins(NotificationDTO notification) {
log.debug("Diffusion d'une notification à {} clients", sessions.size());
String message = notification.toJson();
sessions.values().forEach(session -> {
try {
if (session.isOpen()) {
session.getBasicRemote().sendText(message);
}
} catch (Exception e) {
log.warn("Erreur lors de l'envoi à la session {}",
session.getId(), e);
}
});
}
/**
* Envoie une réponse d'erreur à un client.
*/
private void sendErrorResponse(Session session, String errorMessage) {
try {
String message = String.format(
"{\"type\":\"error\",\"message\":\"%s\"}",
errorMessage
);
session.getBasicRemote().sendText(message);
} catch (Exception e) {
log.error("Impossible d'envoyer la réponse d'erreur", e);
}
}
/**
* Ferme une session WebSocket.
*/
private void closeSession(Session session, String reason) {
try {
session.close(new CloseReason(
CloseReason.CloseCodes.NORMAL_CLOSURE,
reason
));
} catch (Exception e) {
log.warn("Erreur lors de la fermeture de la session", e);
}
}
/**
* Nettoie les ressources d'une session.
*/
private void cleanupSession(Session session) {
try {
session.close();
} catch (Exception e) {
log.warn("Erreur lors du nettoyage de la session", e);
}
}
/**
* Récupère le nombre de clients connectés.
*/
public int getConnectedClientsCount() {
return sessions.size();
}
}