Reputation: 95
We have a spring boot application with axon framework. In a project we have 2 Aggregates which are instantiations of the same abstract aggregate. In short the situation is like this:
@Aggregate
abstract class Fruit {
@AggregateIdentifier
private UUID fruitId;
...
}
class Apple extends Fruit {
@CreationPolicy(CREATE_IF_MISSING)
@CommandHandler()
void myAppleCommand(AppleCommand command) {
...
apply(myAppleEvent);
}
}
class Peer extends Fruit {
@CreationPolicy(CREATE_IF_MISSING)
@CommandHandler()
void myPeerCommand(PeerCommand command) {
...
apply(myPeerEvent);
}
}
The problem is when we should end in a commandhandler myPeerCommand
or myAppleCommand
we expect a new instance of the aggregate to be created, but we get the exception: InstantiationException
.
We could get this @CreationPolicy(CREATE_IF_MISSING)
to work if we make two complete separate aggregates. But al lot of the logic is common is is all Fruit and only a small part is the specific thing for Apple or Peer.
For other problems we use the same construction but now it is for the first time with @CreationPolicy(CREATE_IF_MISSING)
on a command handler.
In our perception this should work, so the question is is this a bug or a feature?
Axon framework v4.9.4 Spring boot 3.2.6 java 21
Upvotes: 1
Views: 88
Reputation: 7275
The only thing I could think about why this wouldn't work, is because the @CreationPolicy
annotated command handlers resolve to the same commandName
.
By the way, the @ComandHandler
annotation defaults the commandName
parameter to the fully qualified class name of the command payload.
The documentation of polymorphic aggregates describes the following "downside" around creational policies:
Having creational command handlers of the same command name on different aggregates in the same hierarchy is forbidden too, since Axon cannot derive which one to invoke.
However, as you can see, this assumes the command name, or in your sample, the command class, is identical. Which, in your Fruit/Apple/Peer example is not.
Having said that, I assume the sample you gave up top does not represent the sample you have in your project. Thus, I just want to confirm: the command class for both @CreationPolicy
annotated methods is not the same in your actual project, right?
If it isn't, I would wager you've hit a bug in Axon Framework. If you would be up for the task, it would be helpful if you could file an issue, with a reproducible scenario, if possible!
Upvotes: 0
Reputation: 401
It's neither. For the aggregate, we need to know the specific class to instantiate. So, it can't be an abstract class. To prevent code duplication, you could create something like Fruity
inside both Apple
and Pear
. If you do this with an @AggregateMember
annotation, you can even have your command handlers inside Fruity
. You can read more about aggregate members in The AxonIQ Library. Feel free to ask any follow-up questions.
Upvotes: 1