Matin Parsapour
Matin Parsapour

Reputation: 67

How to make saga starts

I'm trying to use Axon and Saga design pattern to send data between Micorservices using Java I have two service one for Order and one for Product CQRS Design pattern works perfectly I mean I send data to axon and I see it in my dashboard and then by query data gets and save in read database (MySQL). Today I tried to use Saga design pattern and when create a new order send ReserveProductCommand to axon and gets by Product service but saga doesn't event start and I don't know why

Below Saga class in Order service that should gets OrderCreatedEvent and Log the message but it doesn't

@Saga

public class OrderSaga {

    private final transient CommandGateway commandGateway;

    private static final Logger LOGGER = LoggerFactory.getLogger(OrderSaga.class);

    @Autowired
    public OrderSaga(CommandGateway commandGateway) {
        this.commandGateway = commandGateway;
    }

    @StartSaga
    @SagaEventHandler(associationProperty = "orderId")
    public void handle(OrderCreatedEvent orderCreatedEvent) {
        ReserveProductCommand reserveProductCommand = ReserveProductCommand
                .builder()
                .orderId(orderCreatedEvent.getOrderId())
                .productId(orderCreatedEvent.getProductId())
                .quantity(orderCreatedEvent.getQuantity())
                .userId(orderCreatedEvent.getUserId())
                .build();

        LOGGER.info("OrderCreatedEvent handled for orderId: " + reserveProductCommand.getOrderId() + " and productId: " + reserveProductCommand.getProductId());

        commandGateway.send(reserveProductCommand, new CommandCallback<ReserveProductCommand, Object>() {

            @Override
            public void onResult(CommandMessage<? extends ReserveProductCommand> commandMessage, CommandResultMessage<?> commandResultMessage) {
                if (commandResultMessage.isExceptional()){

                }
            }
        });
    }

    @SagaEventHandler(associationProperty = "orderId")
    public void handle(ProductReservedEvent productReservedEvent){
        LOGGER.info("ProductReservedEvent is called for productId: " + productReservedEvent.getProductId() + " and orderId: " + productReservedEvent.getOrderId());
    }
}

Below OrderCreatedEvent

@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderCreatedEvent {

    public String orderId;
    private String userId;
    private String productId;
    private int quantity;
    private String addressId;
    private OrderStatus orderStatus;
}

I've seen axon dashboard OrderCreatedEvent has been published there

Upvotes: 1

Views: 355

Answers (1)

Mitchell Herrijgers
Mitchell Herrijgers

Reputation: 231

I think the problem is that Axon requires a no-arg constructor on Saga's. You should use field injection for the resources. This passage in the reference guide explains it:

The SpringResourceInjector uses Spring's dependency injection mechanism to inject resources into a Saga. This means you can use setter injection or direct field injection if you require. The method or field to be injected needs to be annotated in order for Spring to recognize it as a dependency, for example with @Autowired.

The passage can be found here: https://docs.axoniq.io/reference-guide/axon-framework/sagas/implementation. Changing the constructor injection to field injection, like the following sample, should work for you:

@Saga

public class OrderSaga {

    @Autowired
    private final transient CommandGateway commandGateway;

    private static final Logger LOGGER = LoggerFactory.getLogger(OrderSaga.class);

    // Abbreviated for clarity
}



Upvotes: 0

Related Questions