Jan
Jan

Reputation: 95

Instantiations of an abstract Axon aggregate with `@CreationPolicy()` on command handers which give an `InstantiationException`, bug or feature?

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

Answers (2)

Steven
Steven

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

Gerard Klijs
Gerard Klijs

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

Related Questions