3

I am playing around with axon server locally. I am running a docker container on my local machine via the command docker run -d --name axonserver -p 8024:8024 -p 8124:8124 axoniq/axonserver.

When I start my spring-boot application, my event handler that is external to an aggregate reruns all previous events so I see this stream of log statements on startup.

The same event handler also publishes a command to an aggregate, which then appends a new event to the aggregate that processes the commands. So my aggregate ends up getting a few events tacked on the end of it each time I reboot the application when I would only want or expected one.

flsh.axon.LetterSchedulingHandler   : Sending letter 0e94035a-ec4b-4fdc-b8b6-4c0bc1927c8f...
flsh.axon.LetterSchedulingHandler   : Sending letter 6b4f6966-85ea-46e0-9c49-21bcd501a1b5...
flsh.axon.LetterSchedulingHandler   : Sending letter fc36292f-c7bd-4575-b56f-130624a87466...

flsh.axon.Letter                    : LetterScheduledEvent 0e94035a-ec4b-4fdc-b8b6-4c0bc1927c8f SCHEDULED
flsh.axon.Letter                    : LetterScheduledEvent 6b4f6966-85ea-46e0-9c49-21bcd501a1b5 SCHEDULED
flsh.axon.Letter                    : LetterScheduledEvent fc36292f-c7bd-4575-b56f-130624a87466 SCHEDULED
flsh.axon.Letter                    : Letter sent fc36292f-c7bd-4575-b56f-130624a87466 SENT
flsh.axon.Letter                    : Letter sent 0e94035a-ec4b-4fdc-b8b6-4c0bc1927c8f SENT
flsh.axon.Letter                    : Letter sent 6b4f6966-85ea-46e0-9c49-21bcd501a1b5 SENT
flsh.axon.Letter                    : Letter sent 0e94035a-ec4b-4fdc-b8b6-4c0bc1927c8f SENT
flsh.axon.Letter                    : Letter sent 0e94035a-ec4b-4fdc-b8b6-4c0bc1927c8f SENT
flsh.axon.Letter                    : Letter sent fc36292f-c7bd-4575-b56f-130624a87466 SENT
flsh.axon.Letter                    : Letter sent 6b4f6966-85ea-46e0-9c49-21bcd501a1b5 SENT

My event handler looks like this:

@Slf4j
@Component
public class LetterSchedulingHandler {

    private final CommandGateway commandGateway;

    public LetterSchedulingHandler(CommandGateway commandGateway) {
        this.commandGateway = commandGateway;
    }

    @DisallowReplay //this doesn't seem to work
    @EventHandler
    public void handle(BeginSendLetterEvent event) {
        log.info("Sending letter {}...", event.getLetterId());
        commandGateway.send(new LetterSentCommand(event.getLetterId()));
    }
}
@CommandHandler
public void handle(LetterSentCommand cmd) {
    AggregateLifecycle.apply(new LetterSentEvent(cmd.getLetterId()));
}

These events are being published via a scheduler...that is is run in an aggregate via a different @CommandHandler and do otherwise get successfully run as expected.

@CommandHandler
public Letter(ScheduleLetterCommand cmd, EventScheduler scheduler) {
    String id = cmd.getLetterId();
    log.info("Received schedule command for letter id {}", id);
    ScheduleToken scheduleToken = scheduler.schedule(Duration.ofSeconds(5), new BeginSendLetterEvent(id));
    AggregateLifecycle.apply(new LetterScheduledEvent(id, scheduleToken));
}

The @DisallowReplay annotation doesn't seem to prevent this. Also, I tried to follow the directions here to make the handler a Subscribing event processor but either I didn't do it right or it also didn't solve the problem.

axon:
  axonserver:
    servers: localhost
  eventhandling:
    processors:
      LetterSchedulingHandler:
        mode: subscribing
Steven
  • 6,936
  • 1
  • 16
  • 31
GoldFlsh
  • 1,095
  • 2
  • 11
  • 26

1 Answers1

3

What you're missing @GoldFLsh, is either of these two:

  1. Correctly reference the EventProcessor behind your LetterSchedulingHandler
  2. Define the @ProcessingGroup of your LetterSchedulingHandler

What you might have read in the Reference Guide on Event Processors, as that any Event Handling Component (read your LetterSchedulingHandler for example) will be grouped with other Event Handling Components in either a subscribing or a tracking event processor.

You have however not configured any processing group name at this stage. This means the LetterSchedulingHandler's processing group will be defaulted to the package name of the handler. Hence, in your properties file you should use the package name instead of LetterSchedulingHandler to define it as being subscribing.

What's clearer though, is to add the @ProcessingGroup annotation on the LetterSchedulingHandler, giving it a clear name you can then use in the properties file.

Lastly, the fact you are not correctly referencing the Event Processor is why you'll see replays of events. Axon defaults to a TrackingEventProcessor which keeps track of how far it is with handling events of the stream. Without a persistence unit to store these TrackingTokens in, it will always start from scratch.

Steven
  • 6,936
  • 1
  • 16
  • 31
  • Looks like there was also a bug in my application.yaml the property "path" is incorrect it should also include eventhandling in the path. Should I just edit the question or should you add that detail to your answer? :) I have also had to make the other recommendations in your answer. – GoldFlsh Jan 24 '20 at 21:42
  • Looks like when I did that, I got this error -> `Description: A component required a bean named 'eventBus' that could not be found. Bean method 'eventStore' in 'AxonAutoConfiguration' not loaded because @ConditionalOnBean (types: org.axonframework.eventsourcing.eventstore.EventStorageEngine; SearchStrategy: all) did not find any beans of type org.axonframework.eventsourcing.eventstore.EventStorageEngine` – GoldFlsh Jan 24 '20 at 21:45
  • Removing `processors.{name}.source: eventbus` did fix that... – GoldFlsh Jan 24 '20 at 21:48
  • 1
    The `EventBus` would be the default source, yes, so omitting it is fine. And you're right that you missed out on the `eventhandling` part in the shared properties file. I've taken the liberty to adjust the sample accordingly. – Steven Jan 27 '20 at 07:48