# Orchestration-Based Saga Implementation ## Architecture Overview A **central orchestrator** (Saga Coordinator) manages the entire transaction flow, sending commands to services and handling responses. ``` Saga Orchestrator / | \ Service A Service B Service C ``` ## Orchestrator Responsibilities 1. **Command Dispatch**: Send commands to services 2. **Response Handling**: Process service responses 3. **State Management**: Track saga execution state 4. **Compensation Coordination**: Trigger compensating transactions on failure 5. **Timeout Management**: Handle service timeouts 6. **Retry Logic**: Manage retry attempts ## Axon Framework Implementation ### Saga Class ```java @Saga public class OrderSaga { @Autowired private transient CommandGateway commandGateway; @StartSaga @SagaEventHandler(associationProperty = "orderId") public void handle(OrderCreatedEvent event) { String paymentId = UUID.randomUUID().toString(); ProcessPaymentCommand command = new ProcessPaymentCommand( paymentId, event.getOrderId(), event.getAmount(), event.getItemId() ); commandGateway.send(command); } @SagaEventHandler(associationProperty = "orderId") public void handle(PaymentProcessedEvent event) { ReserveInventoryCommand command = new ReserveInventoryCommand( event.getOrderId(), event.getItemId() ); commandGateway.send(command); } @SagaEventHandler(associationProperty = "orderId") public void handle(PaymentFailedEvent event) { CancelOrderCommand command = new CancelOrderCommand(event.getOrderId()); commandGateway.send(command); end(); } @SagaEventHandler(associationProperty = "orderId") public void handle(InventoryReservedEvent event) { PrepareShipmentCommand command = new PrepareShipmentCommand( event.getOrderId(), event.getItemId() ); commandGateway.send(command); } @EndSaga @SagaEventHandler(associationProperty = "orderId") public void handle(OrderCompletedEvent event) { // Saga completed successfully } } ``` ### Aggregate for Order Service ```java @Aggregate public class OrderAggregate { @AggregateIdentifier private String orderId; private OrderStatus status; public OrderAggregate() { } @CommandHandler public OrderAggregate(CreateOrderCommand command) { apply(new OrderCreatedEvent( command.getOrderId(), command.getAmount(), command.getItemId() )); } @EventSourcingHandler public void on(OrderCreatedEvent event) { this.orderId = event.getOrderId(); this.status = OrderStatus.PENDING; } @CommandHandler public void handle(CancelOrderCommand command) { apply(new OrderCancelledEvent(command.getOrderId())); } @EventSourcingHandler public void on(OrderCancelledEvent event) { this.status = OrderStatus.CANCELLED; } } ``` ### Aggregate for Payment Service ```java @Aggregate public class PaymentAggregate { @AggregateIdentifier private String paymentId; public PaymentAggregate() { } @CommandHandler public PaymentAggregate(ProcessPaymentCommand command) { this.paymentId = command.getPaymentId(); if (command.getAmount().compareTo(BigDecimal.ZERO) <= 0) { apply(new PaymentFailedEvent( command.getPaymentId(), command.getOrderId(), command.getItemId(), "Payment amount must be greater than zero" )); } else { apply(new PaymentProcessedEvent( command.getPaymentId(), command.getOrderId(), command.getItemId() )); } } } ``` ## Axon Configuration ```yaml axon: serializer: general: jackson events: jackson messages: jackson eventhandling: processors: order-processor: mode: tracking source: eventBus axonserver: enabled: false ``` ## Maven Dependencies for Axon ```xml org.axonframework axon-spring-boot-starter 4.9.0 // Use latest stable version ``` ## Advantages and Disadvantages ### Advantages - **Centralized visibility** - easy to see workflow status - **Easier to troubleshoot** - single place to analyze flow - **Clear transaction flow** - orchestrator defines sequence - **Simplified error handling** - centralized compensation logic - **Better for complex workflows** - easier to manage many steps ### Disadvantages - **Orchestrator becomes single point of failure** - can be mitigated with clustering - **Additional infrastructure component** - more complexity in deployment - **Potential tight coupling** - if orchestrator knows too much about services ## Eventuate Tram Sagas Eventuate Tram is an alternative to Axon for orchestration-based sagas: ```xml io.eventuate.tram.sagas eventuate-tram-sagas-spring-starter 0.28.0 // Use latest stable version ``` ## Camunda for BPMN-Based Orchestration Use Camunda when visual workflow design is beneficial: **Features**: - Visual workflow design - BPMN 2.0 standard - Human tasks support - Complex workflow modeling **Use When**: - Business process modeling needed - Visual workflow design preferred - Human approval steps required - Complex orchestration logic ## When to Use Orchestration Use orchestration-based sagas when: - Building brownfield applications with existing microservices - Handling complex workflows with many steps - Centralized control and monitoring is critical - Organization wants clear visibility into saga execution - Need for human intervention in workflow