【问题标题】:Axon - State Stored Aggregates exception in testAxon - 测试中的状态存储聚合异常
【发布时间】:2020-11-27 07:28:04
【问题描述】:

环境设置:Axon 4.4,H2Database(我们正在做组件测试作为 CI 的一部分) 代码看起来像这样。

    @Aggregate(repository = "ARepository")
    @Entity
    @DynamicUpdate
    @Table(name = "A")
    @Getter
    @Setter
    @NoArgsConstructor
    @EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
    @Log4j2
    Class A implements Serializable {
    
    
      @CommandHandler
      public void handle(final Command1 c1) {
        apply(EventBuilder.buildEvent(c1));
      }
    
      @EventSourcingHandler
      public void on(final Event1 e1) {
      //some updates to the modela
        apply(new Event2());
      }
    
      @Id
      @AggregateIdentifier
      @EntityId
      @Column(name = "id", length = 40, nullable = false)
      private String id;
    
       @OneToMany(
          cascade = CascadeType.ALL,
          fetch = FetchType.LAZY,
          orphanRemoval = true,
          targetEntity = B.class,
          mappedBy = "id")
      @AggregateMember(eventForwardingMode = ForwardMatchingInstances.class)
      @JsonIgnoreProperties("id")
      private List<C> transactions = new ArrayList<>();
    }
    
    @Entity
    @Table(name = "B")
    @DynamicUpdate
    @Getter
    @Setter
    @NoArgsConstructor
    @EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
    @Log4j2
    Class B implements Serializable {
    
      @Id
      @EntityId
      @Column(name = "id", nullable = false)
      @AggregateIdentifier
      private String id;
    
      @ManyToOne(fetch = FetchType.LAZY)
      @JoinColumns({@JoinColumn(name = "id", referencedColumnName = "id")})
      @JsonIgnoreProperties("transactions")
      private A a;
    
      @EventSourcingHandler
      public void on(final Event2 e2) {
       //some updates to the model
      }
    }

我正在使用状态存储聚合,但在嵌入 H2 的 Spring 测试期间,我不断收到错误消息。非嵌入式模式下的 PGSQL DB 不会出现同样的问题,但我们无法在管道中运行它。

错误:“java.lang.IllegalStateException:尚未设置聚合标识符。它必须最迟在应用创建事件时设置”

我通过了 AnnotatedAggregate

    protected <P> EventMessage<P> createMessage(P payload, MetaData metaData) {
            if (lastKnownSequence != null) {
                String type = inspector.declaredType(rootType())
                                       .orElse(rootType().getSimpleName());
                long seq = lastKnownSequence + 1;
                String id = identifierAsString();
                if (id == null) {
                    Assert.state(seq == 0,
                                 () -> "The aggregate identifier has not been set. It must be set at the latest when applying the creation event");
                    return new LazyIdentifierDomainEventMessage<>(type, seq, payload, metaData);
                }
                return new GenericDomainEventMessage<>(type, identifierAsString(), seq, payload, metaData);
            }
            return new GenericEventMessage<>(payload, metaData);
        }

这个序列被设置为 2,因此它抛出异常而不是懒惰地初始化聚合

对此有什么解决办法?我是否缺少某些配置或需要修复 Axon 代码?

【问题讨论】:

  • 您介意补充一下您是如何使用 Axon 的测试夹具来测试您的聚合体的吗?期望在非弹簧式测试夹具中自动连接所有内容可能是罪魁祸首。

标签: spring hibernate jpa axon


【解决方案1】:

我相信您得到的异常是指向您所缺少的 @Rohitdev 的指针。在 Axon 中创建聚合时,它至少假设您将设置聚合标识符。因此,您将填写聚合中存在的 @AggregateIdentifier 注释字段。

这是一个强制验证,因为没有聚合标识符,您基本上缺少对聚合的外部引用。因此,您只需能够将以下命令分派到此聚合,因为无法路由它们。

从您共享的代码 sn-ps 中,没有任何迹象表明聚合 AB 中的 @AggregateIdentifier 注释 String id 字段已设置。不结合使用 Axon 的测试夹具这样做会导致您遇到异常。

使用状态存储聚合时,请注意您将在命令处理程序中更改聚合的状态。这意味着接下来要在命令处理程序中调用 AggregateLifecycle#apply(Object) 方法,您需要将 id 设置为所需的聚合标识符。

根据这个问题,还有两个主要的其他指针可以分享。 聚合内没有创建聚合本身的命令处理程序。您应该在聚合中使用 @CommandHandler 注释构造函数,或者使用 @CreationPolicy 注释将常规方法定义为聚合的创建点(如参考指南中的 here 所述)。

最后,您的示例 仍然 使用 @EventSourcingHandler 注释函数,当您有事件源聚合时应该使用这些函数。听起来您已经有意识地决定反对事件溯源,因此我也不会在您的模型中使用这些注释。目前,它可能只会让开发人员感到困惑,因为它混合使用了状态存储和事件源聚合逻辑。

【讨论】:

  • 史蒂文,标识符已设置。我试图创建一个伪代码,因为我无法共享我们正在处理的代码。当 String id = identifierAsString() 时,标识符已设置但它不存在于 bytebuddy 创建的休眠代理对象中。这会导致标识符返回为 null,这不应该是这种情况。当从邮递员集合中测试此服务时,它可以工作,但在使用 h2db 进行单元/组件测试的情况下,它会显示此问题。
  • 分享标识符的设置方式会更清楚,尤其是在缺少标识符的情况下。最重要的是,分享您如何使用测试夹具将是有益的;该设置或测试准备可能有问题。
  • 它使用 Spring MVC 测试(嵌入式 H2)而不是 Axon 测试
  • 老实说,这只会更加确定这不是 Axon 问题,而是您端的配置问题......
  • 我会看看你在测试中设置的 h2。如有必要,请确保聚合的状态实际上在测试之间保持不变。如果不需要维护,请确保在进行以下测试之前将其清理干净。此外,您说它“随机”发生。真的是随机失败吗?一定有某种启发式方法使它在某些情况下始终失败。
【解决方案2】:

最后调试后发现在B类中我们没有设置更新事件的id

@EventSourcingHandler
 public void on(final Event2 e2) {
    this.id=e2.getId();
 }

一旦我们这样做了,问题就消失了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-10
    相关资源
    最近更新 更多