public interface MyAggregate extends EventSourcedAggregateRoot {
@CommandHandler
void handle(MyCommand command);
}
public class MyAggregateImpl extends AbstractAnnotatedAggregateRoot implements MyAggregate {
@Override
public void handle(MyCommand command)
//do stuff
}
}
Tests are done using: FixtureConfiguration fixture = Fixtures.newGivenWhenThenFixture(MyAggregateImpl.class);
When testing MyCommand, I get a NoHandlerForCommandException. At runtime it works.
I’m simplifying the situation a bit, so let me know if you need any more info.
I am surprised that it works at runtime, to be honest. The test fixture and runtime components use the same mechanism to register command handlers from aggregates. This mechanism doesn’t evaluate annotations placed on interfaces (yet). This means that you must put the @CommandHandler annotation on the declaration of the handle() method in your MyAggregateImpl.
Any idea when this feature will be added to Axon 2 (it worked in Axon 1.4)?
I just double-checked and the handlers from the interface definitely get subscribed at runtime. One thing that is different at runtime compared to test, is that i use an AbstractAggregateFactory (there are multiple implementations of MyAggregate).
Maybe this triggers the interface to be scanned for command handlers?
Now I understand why it works at runtime. The adapter inspects the class that you pass as parameter, and the superclasses of that class. At runtime, you pass the interface class. In the test, the implementation.
Fixing this isn’t too hard. I can schedule it for 2.0.3.
I thought something like “registerCommandHandler(new AggregateAnnotationCommandHandler(MyAggregateInterface.class))” would do, but that doesn’t work.
The best is to mimic your production scenario:
fixture = newGivenWhenThenFixture(MyInterface.class);
fixture.registerAggregateFactory(new GenericAggregateFactory(MyAggregate.class))
This way, the fixture will inspect the interface for annotations, but create instances of the MyAggregate class.
2.0.3-SNAPSHOT contains a fix that will also inspect annotations declared on the interface.
But it doesn’t work: IllegalArgumentException: Given aggregateType may not be abstract. I think on line 1 a GenericAggregateFactory(MyInterface.class) is constructed, which is not allowed.
Anyway, 2.0.3-SNAPSHOT seems to fix the issue, thanks.