首页 > 解决方案 > 应用事件后,聚合标识符必须为非空。确保聚合标识符最迟初始化

问题描述

我收到以下错误。轴突版本 3.3.3

org.axonframework.eventsourcing.IncompatibleAggregateException:应用事件后聚合标识符必须为非空。确保在处理创建事件时最迟初始化聚合标识符。

我创建了一个用户聚合。它包含 2 个事件:

我能够生成第一个 (UserCreated) 事件,它以序列 0 保存在事件存储中,但是在生成第二个事件时,我得到了上述错误。

对此有何建议?

用户聚合.java

@Aggregate
public class UserAggregate {

    @AggregateIdentifier
    private String id;


    private String email;
    private String password;

    public UserAggregate(String id, String email, String password) {
        super();
        this.id = id;
        this.email = email;
        this.password = password;
    }

    @CommandHandler
    public UserAggregate(CreateUser cmd) {
         AggregateLifecycle.apply(new UserCreated(cmd.getId(), cmd.getEmail(), cmd.getPassword()));
    }

    @CommandHandler
    public void handle(UpdateUserCmd cmd) {
         AggregateLifecycle.apply(new UpdateUserEvent(cmd.getId(), cmd.getEmail(),""));
    }

    @EventSourcingHandler
    public void userCreated(UserCreated event) {

        System.out.println("new User: email " + event.getEmail() +" Password: "+ event.getPassword());

        setId(event.getId());




    }

    @EventSourcingHandler
    public void updateUserEvent(UpdateUserEvent event) {

        System.out.println("new User: email " + event.getEmail());

        setId(event.getId());




    }


    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public UserAggregate() {
    }

}

标签: axon

解决方案


我仍在了解 Axon,但这是我设法解决问题的方法。基本上错误的意思是,当UserAggregate被实例化时,聚合标识符(又名主键)不能为空并且必须有一个值。

生命周期的顺序是

  1. 它调用无参数构造函数
  2. 在您的情况下,它会使用您的初始命令调用构造函数。此时,您的聚合标识符仍然为空,我们将在下一步中分配一个值
  3. 然后它调用 aEventSourcingHandler来处理您在上一步中应用的事件

根据上述步骤,您需要执行以下操作:

  1. 创建一个无参数构造函数

protected UserAggregate() {

}
  1. 创建一个处理您的第一个命令的构造函数:

@CommandHandler
public UserAggregate(CreateUser cmd) {
    AggregateLifecycle.apply(
         new UserCreated(cmd.getId(),cmd.getEmail(),cmd.getPassword()));
}
  1. 最后添加一个事件源处理程序来处理UserCreated事件

@EventSourcingHandler
public void on(UserCreated userCreated) {

    // this is where we instantiate the aggregate identifier
    this.id = userCreated.getId();
    
    //assign values to other fields
    this.email = userCreated.getEmail();
    this.password = userCreated.getPassword();

}

这是完整的示例:


@Aggregate
public class UserAggregate {

    @AggregateIdentifier
    private String id;

    private String password;

    private String email;

    protected UserAggregate() {

    }

    @CommandHandler
    public UserAggregate(CreateUser cmd) {
        AggregateLifecycle.apply(
            new UserCreated(cmd.getId(),cmd.getEmail(),cmd.getPassword()));
    }

    @EventSourcingHandler
    public void on(UserCreated userCreated) {

        // this is where we instantiate the aggregate identifier
        this.id = userCreated.getId();

        //assign values to other fields
        this.email = userCreated.getEmail();
        this.password = userCreated.getPassword();

    }
}


推荐阅读