external command handler gives 'Cannot retrieve current AggregateLifecycle; none is yet defined'

I have made a external commandhandler class besides the Aggregate.
When i handle a command in this command handler after a command handled in the aggregate i get ‘Cannot retrieve current AggregateLifecycle; none is yet defined’ . The command is dispatched with a CommandGateway .

It is also reproducable in a unit test with a Aggregatefixture :

@Before
public void setUp() {

    fixture = new AggregateTestFixture<>(DossierAggregate.class);

    fixture.registerInjectableResource(new DefaultCommandGateway(fixture.getCommandBus()));

    fixture.registerAnnotatedCommandHandler(new KikCommandHandler());
}

@Test
public void als_een_kikakte_toegevoegd_wordt_dan_worden_er_events_weggeschreven() {
    StukId stukId = new TIAStukId("NL.IMKAD.TIAStuk.123456789");
    DossierAanmakenMetStukId stukIdAanbieden = new DossierAanmakenMetStukId(stukId.getId());
    Stuk stuk = new TIAStuk("4", "12345", "123");
    KikAkteOpslaan kikAkteOpslaan = new KikAkteOpslaan(new KikAkte(dossierId, stuk));
    fixture
        .givenCommands(stukIdAanbieden)
        .when(kikAkteOpslaan)
        .expectEvents(new TerInschrijvingAangebodenStukAangeboden(dossierId,
            new DeelEnNummer("12345", "123"),
            false,
            null));
}

I have added a jar with the domain events and commands (simplified and all dependent code in one package)


Gerlo Hesselink

axon_external_commandhandler.zip (90.3 KB)

probably has to do with the calling ‘apply’ in the command handler :

public void kikAkteOpslaan(final KikAkteOpslaan command) {
    KikAkte kikAkte = command.getKikAkte();
apply(stukMapper.mapStuk(command.getDossierId(), kikAkte.getStuk()));

which is the Aggregatelifecycle.apply method..  It probably does not now which aggregate it shoud apply on.

wrapping the apply function in the invoke (or execute) function on the aggegate fixes it indeed.
I don’t know if this the way to do it though :

public void kikAkteOpslaan(final KikAkteOpslaan command) {
    KikAkte kikAkte = command.getKikAkte();

Aggregate dossierAggregate = dossierAggregateRepository.load(kikAkte.getDossierId().toString());
dossierAggregate.invoke( c -> apply(stukMapper.mapStuk(command.getDossierId(), kikAkte.getStuk())));

Hello,

AggregateLifecycle.apply is indeed meant to be used within the aggregate since it applies the event on that aggregate (which changes aggregate state) and after that dispatch it on the event bus. Is there a specific reason why you have a separate command handler for handling KikAkteOpslaan command and not handling it in DossierAggregate aggregate? My recommendation would be to move command handler to the aggregate since it updates the state of it (think of this as using a DDD approach, all state changes are done in aggregate itself).

Cheers,
Milan.