Como enviar un comando
Tres pasos: definir el payload, construir el comando, registrarlo en el outbox. Igual que con eventos, el outbox garantiza que el envio es atomico con el resto de la transaccion del caso de uso (si la TX revierte, el comando no se emite).
A diferencia de un evento de dominio (que es broadcast — varios suscriptores pueden reaccionar), un comando es dirigido a un servicio (y tenant) especifico. Y a diferencia de un evento, no hay un agregado donde acumularlo: el caso de uso llama al CommandRegistry directamente.
1. Definir el payload
Un record inmutable. Por convencion vive cerca del caso de uso que lo origina:
package com.example.task.usecase;
public record ArchiveTaskCommand(String taskId, String reason) {
}
2. Construir el comando
Command.toSelf(…) construye un comando dirigido al mismo tenant (intra-tenant). Para inter-tenant usa Command.to(targetTenantId, …):
import com.example.commons.messaging.command.Command;
Command<ArchiveTaskCommand> cmd = Command.toSelf(
"task-service",
new ArchiveTaskCommand(taskId, "expired")
);
sourceTenantId se resuelve automaticamente del TenantContextHolder actual. El commandType lo deriva del FQN de la clase del payload. Para el detalle de los campos ver Referencia: Command.
3. Registrarlo en el outbox
Inyecta CommandRegistry (output port) y llama register desde un metodo @Transactional. La anotacion garantiza que el INSERT en outbox_commands se commitea junto con el resto del caso de uso — si la TX revierte, el comando no se emite:
@Service
@RequiredArgsConstructor
class TaskService implements ArchiveTaskUseCase {
private final CommandRegistry commandRegistry;
@Transactional
@Override
public void archive(String taskId) {
Command<ArchiveTaskCommand> cmd = Command.toSelf(
"task-service",
new ArchiveTaskCommand(taskId, "expired")
);
commandRegistry.register(cmd);
}
}
CommandRegistry.register rutea por direction: los comandos creados con Command.to/toSelf van como OUTBOUND y caen en outbox_commands. El OutboxCommandDispatcher (background) los publica al transport en un tick posterior.
Activar el dispatcher de outbox
El dispatcher que saca los comandos del outbox y los publica al transport viene apagado por default. Habilitalo en application.yaml:
app:
commands:
outbox-dispatcher:
enabled: true
Para los demas parametros y defaults ver Referencia: propiedades de mensajeria.
Verificar que salio
curl http://localhost:8080/actuator/message-boxes muestra el conteo de commands.outbox. Para detalle del endpoint ver Inspeccionar las bandejas de mensajeria.
Ver tambien
-
Procesar un comando — del otro lado: como definir el handler que lo recibe.
-
Referencia: Mensajeria —
Command,CommandRegistry, propiedadesapp.commands.*. -
Decisiones de mensajeria — por que comandos y eventos son bandejas separadas.