Patrón de Diseño para Procesamiento de Eventos de Mensajes

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);
        }
    }
}

Etiquetas: patrones de diseño mensajería asíncrona java Spring Framework Arquitectura de eventos

Publicado el 8-3 14:17