Multiple Entity Aggregate command handler

Hi,
I have an aggregate root like this:

Aggregate root:

@NoArgsConstructor
@Aggregate(repository = "positionAggregateRepository")
@AggregateRoot
@XSlf4j
@Data
public class HopAggregate {

    @AggregateIdentifier
    private String hopId;
    private FilteredPosition position;
    private LocalDate positionDate;
    @AggregateMember
    private Security security;

    @CommandHandler
    public HopAggregate(NewHopCommand cmd) {
        log.info("creating new position , {}", cmd.getDateId());
        apply(new HopEvent(cmd.getHopId(), cmd.getDateId(), cmd.getFilteredPosition(), cmd.getSecurity(), false));
    }

    @CommandHandler
    public void handle(UpdateHopCommand cmd) {
        log.info("creating hop update event {}", cmd);
        apply(new HopEvent(this.hopId, this.positionDate, cmd.getFilteredPosition(), this.security, true));
    }

    @CommandHandler
    public void handle(SecurityUpdate cmd) {
        log.info("updating security {}", cmd);
        apply(new SecurityUpdateEvent(this.hopId, cmd.getFilteredSecurity()));
    }

    @EventSourcingHandler
    public void on(HopEvent evt) {
        if (evt.getIsUpdate()) {
            log.info("updating position {}", evt);
            this.position = evt.getFilteredPosition();
        } else {
            log.info("adding new position to date {}", evt);
            this.hopId = evt.getHopId();
            this.positionDate = evt.getDate();
            this.position = evt.getFilteredPosition();
            this.security= evt.getSecurity();
        }
    }

    @EventSourcingHandler
    public void on(SecurityUpdateEvent evt) {
        log.info("hop id {}, security update {}", this.hopId, evt.getFilteredSecurity().getSecurityId());
    }

}

Child entity:

@XSlf4j
@Data
@RequiredArgsConstructor
@NoArgsConstructor
public class IpaSecurity implements Serializable {

    @EntityId
    @NonNull
    private String id;
    @NonNull
    private FilteredSecurity security;
}

My issue is that when i am pushing and update like this:

@EventHandler
public void handleSecurityEvent(SecurityUpdate securityUpdate) {
    log.info("got security event {}", securityUpdate);
    commandGateway.send(securityUpdate);
}

and my command being

@Data
@RequiredArgsConstructor
@NoArgsConstructor
@ToString
public class SecurityUpdate {

    @NonNull
    @TargetAggregateIdentifier
    private String id;
    @NonNull
    private FilteredSecurity filteredSecurity;

}

I am getting aggregate root not found exception:

Command ‘com.hb.apps.ipa.events.SecurityUpdate’ resulted in org.axonframework.modelling.command.AggregateNotFoundException(The aggregate was not found in the event store)

I am not sure how to handle this scenario. My requirement is that each aggregate should check whether it contains the security and then update it if the command was issued. What am i missing? let me know if you need any more info on the code.

Thanks for your help.

Is there a way to apply command to all aggregates and let them decide whether the event is applicable to them?

Hi Somil,

My hunch is that you’re receiving this exception because you have both the @Aggregate and @AggregateRoot annotation.
The @Aggregate is already meta-annotated with @AggregateRoot and thus you’re essentially duplicating the annotation.
Additionally, you’re defining the repository you want to use for this Aggregate.
Having both annotations might make it somewhat flaky which decision is made in regards to the repository being used.

I’d thus suggest to remove the @AggregateRoot, as it is redundant in your set up.

If removing it doesn’t solve the issue, then you very likely have a discrepancy between the @AggregateIdentifier annotated field in your Aggregate and the @TargetAggregateIdentifier annotated field in your Command message.

Next to that, I want to emphasize on the naming of your commands and events.
To be clear to any developer in your team, you should ensure that commands are Present Tense and events are Past Tense.

A Command models the desire for something to happen, whilst an Event is stating that something has happened; this should be apparent from your command and event classes too.

Then for the following question you have:

Is there a way to apply command to all aggregates and let them decide whether the event is applicable to them?
No, the framework has no built int support for this.
It is however perfectly fine to model this yourself in your set up, by having a Command Handling component that handles ‘SomeBulkCommand’, which in turn issues ‘SomeCommand’ towards every aggregate in your system.

Hope this helps!

Cheers,
Steven