java - Axon 错误 : java. lang.IllegalArgumentException:工作单元已具有具有相同标识符的聚合

标签 java cqrs axon

我有一个正在处理报告运行命令的报告运行程序聚合。聚合具有目标标识符,并且两个命令具有相同的目标标识符。

出现以下错误

java.lang.IllegalArgumentException: The Unit of Work already has an Aggregate with the same identifier at org.axonframework.common.Assert.isTrue(Assert.java:54) ~[axon-core-3.0.6.jar:3.0.6] at org.axonframework.commandhandling.model.AbstractRepository.newInstance(AbstractRepository.java:84) ~[axon-core-3.0.6.jar:3.0.6] at org.axonframework.commandhandling.AggregateAnnotationCommandHandler$AggregateConstructorCommandHandler.handle(AggregateAnnotationCommandHandler.java:181) ~[axon-core-3.0.6.jar:3.0.6] at org.axonframework.commandhandling.AggregateAnnotationCommandHandler$AggregateConstructorCommandHandler.handle(AggregateAnnotationCommandHandler.java:170) ~[axon-core-3.0.6.jar:3.0.6] at org.axonframework.commandhandling.AggregateAnnotationCommandHandler.handle(AggregateAnnotationCommandHandler.java:148) ~[axon-core-3.0.6.jar:3.0.6] at org.axonframework.commandhandling.AggregateAnnotationCommandHandler.handle(AggregateAnnotationCommandHandler.java:40) ~[axon-core-3.0.6.jar:3.0.6]

类似

public class ExecuteReportsAggregate
{
    @AggregateIdentifier
    private String reportId; 

    // Command Handler and Even Source Handlers
}

执行报告命令

@Value
public class ExecuteReportCommand
{
    @TargetAggregateIdentifier
    String reportId;
}

报告执行的命令

@Value
public class ReportExecutedCommand
{
    // @TargetAggregateIdentifier
    private String reportId;
}

Spring 启动看起来像这样

public static void main(String[] args)
{
    ConfigurableApplicationContext config = SpringApplication.run(SsmpPreopenCommand.class, args);
    CommandBus commandBus = config.getBean(CommandBus.class);

    commandBus.dispatch(GenericCommandMessage.asCommandMessage(new ExecuteReportCommand("12345",
        "asdfasdf Errors", "/home/teo", new ServiceCredentials())));

    // commandBus.dispatch(GenericCommandMessage.asCommandMessage(new
    // ReportExecutedCommand("12345")));
}

最佳答案

Axon 正在处理您实现的聚合实例。因此,您可以通过使用 @CommandHandler 来标记 Aggregate 的相关方法。注释。

(通常)聚合应该具有:

  • 无参数构造函数
  • 以命令作为第一个参数的构造函数,标记为 @CommandHandler注释
  • 至少一种标有 @EventSourcingHandler 的方法注释,接受由执行此构造函数引发的事件作为第一个参数,该构造函数由 AggregateLifecycle#apply() 执行方法并设置 AggregateIdentifier 标记的字段.
  • 任何数量的其他方法,接受命令作为第一个参数,标记为 @CommandHandler注释
  • 任何数量的其他方法,接受事件作为第一个参数,标记为 @EventSourcingHandler注释

如果您在 CommandBus 上发送第一个命令,Axon 将尝试查找具有匹配标识符的聚合,并且由于它尚不存在,因此通过调用构造函数并将命令传递给它来创建它。构造函数将调用AggregateLifecycle#apply()方法并触发事件(由 Axon 存储),因此从此时开始,Axon 将尝试发送具有相同 TargetAggregateIdentifier所有命令。到这个聚合实例。

如果您尝试创建(并存储)具有相同聚合标识符的相同类型的另一个聚合实例,您将失败并看到上面的异常。

为了避免这种情况,您需要使用“create-on-check-fail”模式。看我的thoughts on it here...

亲切的问候,

西蒙

关于java - Axon 错误 : java. lang.IllegalArgumentException:工作单元已具有具有相同标识符的聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46813394/

相关文章:

java - 为什么类无法转换为它实现的接口(interface)?

java - 向列添加数据的简单方法

architecture - 没有 CQRS 的事件溯源

angular - ngxs 异步操作的成功/失败操作事件的目的是什么?

android - 轴突框架 : Android support?

kotlin - 如何从 Kotlin AllOpen 插件中排除注释?

java - 轴突框架 : How to rollback in the domain_event_entry table

java - 将数据库密码保留在 spring-servlet.xml 文件之外

java - SendRedirect 与 Java Servlet 中的转发用例

akka - 使用 akka-persistence 实现 CQRS + 事件溯源