First, the actual question: Is there an example of how to use aggregate factories with an aggregate class hierarchy in Axon 3?
Now the details. Context is that I have a few related aggregate root classes with some of the command handlers defined in the superclass (RequestAggregate) and others in the subclasses (RegisterRequestAggregate, etc.)
In Axon 2, I registered a single factory, attached it to a repository, and registered a command handler for each subclass, like so:
<bean id="requestAggregateFactory" class="com.xyz.RequestAggregateFactory" />
<axon:event-sourcing-repository id="requestAggregateRepository"
aggregate-factory="requestAggregateFactory"
event-bus="eventBus"
event-store="eventStore" />
<axon:aggregate-command-handler aggregate-type="com.xyz.CancelRequestAggregate"
repository="requestAggregateRepository"
command-bus="commandBus" />
<axon:aggregate-command-handler aggregate-type="com.xyz.RegisterRequestAggregate"
repository="requestAggregateRepository"
command-bus="commandBus" />
<axon:aggregate-command-handler aggregate-type="com.xyz.ValidateRequestAggregate"
repository="requestAggregateRepository"
command-bus="commandBus" />
In Axon 3, I try to configure the factory and the aggregates (I'm letting autoconfiguration build the repository for me):
configurer.configureAggregate(
AggregateConfigurer.defaultConfiguration(RequestAggregate.class)
.configureAggregateFactory(c -> new RequestAggregateFactory()));
configurer.configureAggregate(CancelRequestAggregate.class);
configurer.configureAggregate(RegisterRequestAggregate.class);
configurer.configureAggregate(ValidateRequestAggregate.class);
And this sort of works in that the factory gets called to instantiate the aggregate when the initial creation command is dispatched. But none of the subclass command handler methods are recognized; if I try to send a subclass-specific command, Axon throws an exception saying it can't find the command handler. Commands whose handlers are on the superclass work fine.
The problem seems to be that when the configuration is initialized, the AbstractRepository constructor calls ModelInspector.inspectAggregate() and passes it the superclass (as returned by the getType() method on the factory bean) rather than one of the subclasses. So the aggregate model only contains the superclass command handler methods.
It doesn't work to modify the factory to return a subclass from getType() because then the factory will claim it's a producer of, say, CancelRequestAggregate instances but will return a RegisterRequestAggregate instead if you pass it a particular kind of command.
I tried declaring the factory bean with a bunch of aliases so it would be associated with all the aggregates by autoconfiguration, but that ended up behaving the same as the explicit call above.
I also tried getting rid of the factory and seeing if autoconfiguration would figure it out, but that ends up not working either; I get an IncompatibleAggregateException because commands end up getting routed to the wrong subclasses.
Hopefully there's an example I can look at to see how this is supposed to be done; I expect I'm failing to understand something fundamental. I only found one Axon JUnit test that uses aggregate factories and it doesn't use a class hierarchy, just a single aggregate class.
-Steve