1. Implementación del patrón para el menejo de eventos basado en una cola de mensajes
Esta aproximación define una arquitectura para procesar mensajes de forma estructurada, permitiendo el registro y ejecución ordenada de múltiples manejadores específicos.
① Interfaz abstracta para el manejador de mansajes
public interface ProcesadorEventoMensaje {
/**
* Obtiene el identificador único del procesador.
* @return Nombre del procesador.
*/
String obtenerIdentificador();
/**
* Define el orden de ejecución del procesador.
* @return Valor entero que indica la prioridad.
*/
Integer obtenerPrioridad();
/**
* Lógica principal para procesar el evento.
* @param eventoDatos Objeto con los datos del evento.
*/
void ejecutar(ObjetoEvento eventoDatos);
/**
* Valida si este procesador debe manejar el evento.
* @param eventoDatos Datos del evento a validar.
* @return true si el procesador es responsable.
*/
boolean esResponsable(ObjetoEvento eventoDatos);
}
② Clace base abstracta para los procesadores
public abstract class ProcesadorEventoAbstracto implements ProcesadorEventoMensaje {
@Autowired
protected RegistroProcesadores registroProcesadores;
protected String nombreClase;
protected Integer prioridadBase = 100;
@PostConstruct
public void inicializar() {
this.nombreClase = this.getClass().getSimpleName();
this.registroProcesadores.agregarProcesador(this);
}
@Override
public String obtenerIdentificador() {
return this.nombreClase;
}
@Override
public Integer obtenerPrioridad() {
return this.prioridadBase;
}
@Override
public abstract void ejecutar(ObjetoEvento eventoDatos);
@Override
public abstract boolean esResponsable(ObjetoEvento eventoDatos);
}
③ Orquestador central de procesadores
@Slf4j
@Component
public class RegistroProcesadores {
private final List<procesadoreventomensaje> procesadores = new CopyOnWriteArrayList<>();
public void agregarProcesador(ProcesadorEventoMensaje nuevoProcesador) {
this.procesadores.add(nuevoProcesador);
this.procesadores.sort(Comparator.comparingInt(ProcesadorEventoMensaje::obtenerPrioridad));
}
public void despacharEvento(ObjetoEvento eventoDatos) {
if (procesadores.isEmpty()) {
log.warn("No hay procesadores registrados para el evento: {}", eventoDatos);
return;
}
for (ProcesadorEventoMensaje procesador : procesadores) {
try {
if (procesador.esResponsable(eventoDatos)) {
log.info("Procesador {} maneja el evento", procesador.obtenerIdentificador());
procesador.ejecutar(eventoDatos);
return; // Procesado por el primer responsable
}
} catch (Exception ex) {
log.error("Error en procesador {} al manejar evento", procesador.obtenerIdentificador(), ex);
}
}
}
}</procesadoreventomensaje>
④ Procesador concreto para asignación de recompensas
@Slf4j
@Component
public class ProcesadorRecompensas extends ProcesadorEventoAbstracto {
@Autowired
private ServicioRecompensas servicioRecompensas;
@Override
public void ejecutar(ObjetoEvento eventoDatos) {
SolicitudRecompensa solicitud = mapearDatos(eventoDatos.getDatos(), SolicitudRecompensa.class);
servicioRecompensas.procesarSolicitud(solicitud);
}
@Override
public boolean esResponsable(ObjetoEvento eventoDatos) {
return "ASIGNACION_RECOMPENSA".equals(eventoDatos.getTipoEvento());
}
}
⑤ Listener que conecta la cola con el orquestador
@Slf4j
@Component
public class ListenerColaMensajes {
@Autowired
private RegistroProcesadores registroProcesadores;
@ColaListener(nombreCola = "${config.cola.eventos}")
public void alRecibirMensaje(String mensajeCrudo) {
log.debug("Mensaje recibido: {}", mensajeCrudo);
try {
ObjetoEvento evento = parsearJson(mensajeCrudo, ObjetoEvento.class);
if (evento != null && evento.esValido()) {
registroProcesadores.despacharEvento(evento);
}
} catch (Exception e) {
log.error("Error procesando mensaje de la cola", e);
}
}
}