Axon 框架:更改 @EventHandler 和 @EventSourcingHandler 之间的处理顺序 [英] Axon Framework: Change processing order between @EventHandler and @EventSourcingHandler

查看:31
本文介绍了Axon 框架:更改 @EventHandler 和 @EventSourcingHandler 之间的处理顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题是如何更改 @EventHandler@EventSourcingHandler 之间的处理顺序,对于同一个给定的事件.我在 Aggregate 类中有 @EventSourcinHandler 方法,在外部类中有 @EventHandler 方法.如果我触发导致所述事件事件的命令,我的代码将像这样运行:

My question is how I can change the processing order between an @EventHandler and an @EventSourcingHandler, for the same given Event. I have the @EventSourcinHandler method in an Aggregate class and an @EventHandler in an external class. If i fire an command which results in said event event, my code will run like this:

  1. @EventSourcingHandler
  2. @EventHandler

我想把这个顺序改成这样:

I want to change this order to this:

  1. @EventHandler
  2. @EventSourcingHandler

我尝试了 @Order@ProcessingGroup 批注,但在调整顺序方面,这些都不适合我.

I tried the @Order and @ProcessingGroup annotations, but none of these worked for me in regards to adjusting the order.

这是我的聚合实现:

@Aggregate
@Getter
@Setter
@NoArgsConstructor
@Order(2)
@ProcessingGroup("template")
@Component
public class TemplateAggregate {

  private static final transient Logger logger = LoggerFactory.getLogger(TemplateAggregate.class);
  @AggregateIdentifier
  private String templateId;

  private LocalDate createdAt;

  private String createdBy;

  private String description;

  private LocalDate modifiedAt;

  private String modifiedBy;

  private String name;

  private LocalDate validFrom;

  private LocalDate validTo;

  private File file;

  private String fileName;

  private long fileSize;

  private LocalDate fileDate;

  private String fileUploader;

  @CommandHandler
  public TemplateAggregate(CreateTemplateCommand cmd) {
    AggregateLifecycle.apply(new TemplateCreatedEvent(cmd));
  }

  @CommandHandler
  public void handle(ModifyTemplateCommand cmd) {
    AggregateLifecycle.apply(new TemplateModifiedEvent(cmd));
  }

  @EventSourcingHandler
  public void on(TemplateCreatedEvent event) {
    this.templateId = event.getTemplateId();
    this.createdAt = event.getCreatedAt();
    this.createdBy = event.getCreatedBy();
    this.description = event.getDescription();
    this.name = event.getName();
    this.validFrom = event.getValidFrom();
    this.validTo = event.getValidTo();
    this.file = event.getFile();
    this.fileName = event.getFileName();
    this.fileSize = event.getFileSize();
    this.fileDate = event.getFileDate();
    this.fileUploader = event.getFileUploader();
    logger.info("TemplateAggregate - TemplateCreatedEvent");
  }

  @EventSourcingHandler
  public void on(TemplateModifiedEvent event) {
    this.templateId = event.getTemplateId();
    this.createdAt = event.getCreatedAt();
    this.createdBy = event.getCreatedBy();
    this.description = event.getDescription();
    this.name = event.getName();
    this.validFrom = event.getValidFrom();
    this.validTo = event.getValidTo();
    this.file = event.getFile();
    this.fileName = event.getFileName();
    this.fileSize = event.getFileSize();
    this.fileDate = event.getFileDate();
    this.fileUploader = event.getFileUploader();
    this.modifiedAt = event.getModifiedAt();
    this.modifiedBy = event.getModifiedBy();
    logger.info("TemplateAggregate - TemplateModifiedEvent");
  }

}

我的外部 EventHandler 类:

My External EventHandler class:

@Service
@Order(1)
@ProcessingGroup("template")
@Component
public class TemplateCreatedEventHandler {

  private static final transient Logger logger =
      LoggerFactory.getLogger(TemplateCreatedEventHandler.class);

  @Autowired
  private TemplateRepository templateRepository;

  @Transactional
  @EventHandler
  public void on(TemplateCreatedEvent event) {
    templateRepository.save(new TemplateQueryEntity(event));
    logger.info("EventHandler - TemplateCreatedEvent");
  }

}

我想这样做,因为我想首先将所有内容保存在我的数据库中,因此在此期间如果出现异常,Axon 无法保存在 domain_event_entry 表中.

I want to do this, because I want to first persist everything in my database, so during this if i get an exception, Axon could not persist in the domain_event_entry table.

推荐答案

@EventSourcingHandler 用于事件溯源.它在两个不同的时刻更新聚合的状态:第一次应用事件时,在这种情况下,它作为 apply() 方法的一部分被立即调用,其次,当聚合状态被重建时基于其事件.

The @EventSourcingHandler is used for Event Sourcing purposes. It updates the state of your aggregate at two distinct moments: when the event is first applied, in which case it is invoked immediately as part of the apply() method, and secondly when the aggregate state is reconstructed based on its events.

这意味着聚合中的 @EventSourcingHandler总是在任何外部事件处理程序能够接收事件之前被调用.这不是你可以改变的,坦率地说,我相信这也不是你想要的.

That means the @EventSourcingHandler within an Aggregate will always be invoked before any external event handlers are able to receive the event. This is not something you can change, and quite frankly, I'm sure that's also not what you want.

您提到要确保首先将所有内容保存在我的数据库中".如果你想以事件驱动的方式工作,这是放手"的第一个原则.主要的真相是你的事件.你首先要坚持这些.然后,作为这些事件的结果,您更新其他表格,这些表格提供视图、产生其他副作用等.

You mention that you want to be sure that you "want to first persist everything in my database". If you want to work in an event-driven way, this is the first principle to "let go". The primary truth is your events. You'd want to persist these first. Then, as a result of these events, you update the other tables, which feed views, generate other side-effects, etc.

如果出于某种原因,您确实希望确保您的视图模型和事件的事务更新,您可以将包含您的外部事件处理程序的处理组分配给订阅处理器.这使您能够在处理命令(并发布事件)的同一事务中调用事件处理程序.

If for whatever reason, you do want to ensure transactional update of your View models and your events, you can assign the Processing Group that contains your external event handler to a Subscribing Processor. This gives you the ability to invoke the Event Handler in the same transaction that also handles the Command (and publishes the events).

另外,我注意到您的聚合包含很多字段.通常,聚合只需要包含实际用于对传入命令做出决策的字段.命令模型中聚合根的 Getter(和 Setter,就此而言)通常是一种设计风格,因为它们根本不需要专注于公开信息.聚合上的 @Order@ProcessingGroup@Component 注释没有用途,可以删除.

Also, I noticed that your aggregate contains a lot of fields. Generally, an Aggregate only needs to contains the fields that are actually used to make decisions on incoming commands. Getters (and Setters, for that matter) on Aggregate Roots in Command Models are generally a design-smell, as they shouldn't need to focus on exposing information at all. The @Order, @ProcessingGroup and @Component annotations on your aggregate have no purpose, and can be removed.

这篇关于Axon 框架:更改 @EventHandler 和 @EventSourcingHandler 之间的处理顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆