Axon EventHandler не получает событие

Мне нужна помощь с правильной настройкой приложения Axon, или я неправильно понимаю аксон. У меня два агрегата:

  • "FileStore", в котором будет храниться информация об индексированных файлах.
  • DirectoryLister, который отправляет события для каждого индексируемого файла.

Проблема, с которой я столкнулся, заключается в том, что "DirectoryLister" отправляет событие, используя

AggregateLifecycle.apply(new IndexedFileEvent(...)); 

А внутри DirectoryLister я могу поймать событие в EventSourcingHandler. Но внутри «FileStore» обработчик событий не реагирует. Я проверил, что событие опубликовано в шине событий. Я подумал, что мне нужно использовать «AnnotationEventListenerAdapter», чтобы каким-то образом заставить FileStore прослушивать шину событий, но я не смог найти пример того, как это работает.

Я использую Axon 3.4.3 без Spring и настраиваю приложение следующим образом:

    Configurer configer = DefaultConfigurer.defaultConfiguration();
    configer.configureEmbeddedEventStore(c -> new InMemoryEventStorageEngine());
    // configure two Aggregates
    configer.configureAggregate(FileStore.class);
    configer.configureAggregate(DirectoryLister.class);

    // how can I register FileStore as an eventListener? Using AnnotationEventListenerAdapter?

    Configuration config = configer.buildConfiguration();

    // verify that event is published on the event bus
    config.eventBus().subscribe(l -> l.forEach( e -> System.out.println(e.toString())));
    config.start();

Класс FileStore выглядит так:

public class FileStore {
    @AggregateIdentifier String id; 

    public FileStore() { }

    @CommandHandler public FileStore(CreateFileStoreCommand command) {
        AggregateLifecycle.apply(new FileStoreCreatedEvent(command.getId()));
    }

    @EventSourcingHandler public void on(FileStoreCreatedEvent event) {
        id = event.getId();
    }

    @EventSourcingHandler public void on(IndexedFileEvent event) {
        System.out.println(event.getParentPath() + "//" + event.getName() + "  " + event.getSize().toString());
    }

Класс "DirectoryLister" выглядит так:

  public class DirectoryLister {
    @AggregateIdentifier String id; 

    protected  DirectoryLister() { }

    @CommandHandler public DirectoryLister(CreateListerCommand cmd) {
        AggregateLifecycle.apply(new CreateListerEvent(cmd.getId()));   
    }

    @CommandHandler public void handleCommand(IndexDirectoryCommand cmd) throws IOException {
         FileVisitor<Path> fv = new SimpleFileVisitor<Path>() {
              @Override
              public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                // this is where the event is sent!
                AggregateLifecycle.apply(new IndexedFileEvent(file.getFileName().toString(),file.getParent().toString(), attrs.size())); 
                return FileVisitResult.CONTINUE;
              }
            };

          Files.walkFileTree(cmd.getPath(), fv);
    }

    @EventSourcingHandler public void on (CreateListerEvent event) { id = event.getId(); }

    // This handler is invoked. 
    @EventSourcingHandler public void on(IndexedFileEvent event) {
        System.out.println(event.getParentPath() + "//" + event.getName() + "  " + event.getSize().toString());
    }
}

person Mathias Mamsch    schedule 13.01.2020    source источник


Ответы (1)


Если я правильно понимаю, вы пытаетесь обрабатывать события, которые были опубликованы из Aggregate DirectoryLister в Aggregate FileStore, правильно?

Однако это предположение невозможно по сути. Агрегат, который вы описываете, по сути, является Командной моделью в настройке CQRS. Таким образом, он обрабатывает команды из внешнего мира, а затем решает, можно ли выполнить данную команду / операцию на этом этапе. В результате определения возможности обработки команды публикуется событие, уведомляющее о том, что «что-то произошло».

Однако командная модель не предназначена для непосредственной обработки событий. Единственный раз, когда он обрабатывает события, - это «источник самого изменения, которое он опубликовал». Вот почему обработчик событий в агрегате - это не @EventHandler в Axon, а @EventSourcingHandler, поскольку он может только обрабатывать события из своего собственного источника.

В Справочном руководстве также указано, что обработка событий из других агрегатов в данном агрегате невозможна (что можно найти в здесь).

Итак, попросту говоря, то, что вы ожидаете, невозможно, Матиас. Вам нужно будет разместить компонент обработки событий между ними, который будет реагировать на заданное событие от DirectoryLister и преобразовывать его в команду, которую вы хотите выполнить на FileStore.

person Steven    schedule 13.01.2020