【问题标题】:Axon Command is delivered to EventHandlerAxon Command 被传递给 EventHandler
【发布时间】:2021-07-24 13:56:44
【问题描述】:

我正在尝试将Command 发送到Aggregate。当我将Command 发送到Aggregate 时,Aggregate 的EventHandler 方法在CommandHanlder 方法之前被调用。 我不知道这怎么可能,因为我只想调用CommandHandler 方法。

首先我发送IssueCardCommand 来创建GiftCard Aggregate 并发送ReimburseCardCommand 来调用AggregateMember 的CommandHandler 方法。

@Autowired
CommandGateway cm;
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
    return args -> {

        String cardId = UUID.randomUUID().toString();
        int transactionValue = (int) (Math.random() * 100);

        cm.sendAndWait(new IssueCardCommand(cardId, transactionValue));
        
        cm.sendAndWait(new ReimburseCardCommand(cardId, transactionValue));

    };
}

这是我想调用的GiftCardTransaction(聚合的子实体)CommandHandler 方法

@CommandHandler
public void handle(ReimburseCardCommand cmd) {
    log.info("GiftCardTransaction Handler " + transactionId);
    log.info(reimbursed);

    // if (reimbursed) {
    // throw new IllegalStateException("Transaction already reimbursed");
    // }
    apply(new CardReimbursedEvent(cmd.getTransactionId(), transactionId, transactionValue));
}

这是Aggregate

@Log4j2
@Aggregate
@NoArgsConstructor
public class GiftCard {

    @AggregateIdentifier
    private String id;

    @AggregateMember(routingKey = "transactionId", eventForwardingMode = ForwardMatchingInstances.class)
    private List<GiftCardTransaction> transactions = new ArrayList<>();

    private int remainingValue;


    @CommandHandler
    public GiftCard(IssueCardCommand cmd) {
        log.info("GiftCard is created");
        apply(new CardIssuedEvent(cmd.getCardId(), cmd.getAmount()));
    }

    @EventSourcingHandler // 4.
    public void on(CardIssuedEvent evt) {
        id = evt.getCardId();
        remainingValue=evt.getAmount();
        log.info(id);
        transactions.add(new GiftCardTransaction(id,remainingValue));
        String cardId = UUID.randomUUID().toString();
        apply(new CardReimbursedEvent(cardId,id,evt.getAmount()));
    }

    @CommandHandler
    public void handle(ReimburseCardCommand cmd) {
        String cardId = UUID.randomUUID().toString();
        apply(new CardReimbursedEvent(cardId,id,cmd.getTransactionValue()));
    }
}

【问题讨论】:

    标签: spring-boot axon


    【解决方案1】:

    当你说

    Aggregate 的 EventHandler 方法在 CommandHanlder 方法之前被调用

    你这是什么意思? 我怀疑您正在体验聚合的事件溯源部分。

    基本上,您的流程应该是这样的:

    1. IssueCardCommand -> 由Aggregate 处理,有效地为您创建一个并应用随后的CardIssuedEvent,这将立即由您的EventSourcingHandler 处理。
    2. ReimburseCardCommand -> 你的Aggregate 是从过去重建的(事件溯源),这意味着所有@EventSourcingHandlers 将在命令处理程序之前被调用。当Aggregate 与事件保持同步时,它将根据@CommandHandler 方法处理您的命令。

    obs:似乎您有一个重复的命令处理程序方法,一个在@Aggregate 上,另一个在@AggregateMember 上。我会仔细检查这是否正确,以及您是否在两个地方都获得了命令,而我认为您不是。

    【讨论】:

    • 感谢您的回答,但为什么会在命令处理程序之前调用@EventSourcingHandlers?
    • 这就是事件溯源的作用。简而言之,您的聚合将“始终”根据过去的事件进行重建,然后才能决定接受或不接受(验证)新命令。因此,所有@EventSourcingHandlers 都将被调用,聚合的状态被重建,并且可以应用(或不应用)新命令。你可以阅读更多关于它here
    猜你喜欢
    • 1970-01-01
    • 2012-01-28
    • 2019-09-11
    • 1970-01-01
    • 2013-06-21
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    相关资源
    最近更新 更多