Axon 0.7 questions

Sorry folks, I don't want to spam the list but creating the Axon
Example Application raises several questions and I hope you can all
benefit from a good example... :slight_smile:

So here are some more questions on new Axon 0.7 features:

1) Why is AggregateIdentifierFactory abstract and not an interface?

I wanted to inject my own implementation here:

This wasn't possible so I created a temporary interface:

2) Why is the DefaultAggregateIdentifier only package visible?

I expected to see a simple and public UUID implementation as I created
one here:
The DefaultAggregateIdentifier seems to be unnecessary "generic" to

Here is my point of view:

  1. I didn’t see the point in creating an interface for it. I don’t want to prescribe how anyone should generate AggregateIdentifier instances. Axon just needs an instance. Whether you want to use a factory or a constructor to generate one is up to you.
    In my projects, I don’t let command handlers generate identifiers. Either the aggregates do it, or (better) the client. Aggregates have a default constructor that generates a UUID-based identifier.

  2. I made it package-visible because it is an internal implementation. If you need an instance, you should use the AggregateIdentifierFactory. If that doesn’t create the AggregateIdentifier you want, you should create your own implementation for the AggregateIdentifier interface.
    And yes, it is generic. This generic form makes it very easy when working with Hibernate, for example. It would be easy to create a AggregateIdentifierUserType that only stores the string representation in the database and always resolves back into a DefaultAggregateIdentifier implementation. That can only be done if it is generic. The usertype isn’t there yet, though, but it will be, soon.

But to be honest, I am not sure about the factory vs constructor way of creating aggregate identifiers. If you guys think it’s easier, I could ditch the AggregateIdentifierFactory and make the DefaultAggregateIdentifier public with a few constructors.



In my projects, I don't let command handlers generate identifiers.

Hmm... What about the "ContactCommandHandler" in the sample app? :wink:

I don't want to prescribe how anyone should generate AggregateIdentifier instances.
Axon just needs an instance. Whether you want to use a factory or a constructor
to generate one is up to you.

Absolutely correct. But I think it's nontheless a good idea to open up
a possibility to create the AggregateIdentifier other ways. At least
this was my idea from the original discussion:

I don't think the abstract class is a good idea - It makes things more
complicated for the ones like you who want to use an UUID based
identifier. The others like me that prefer a clean separation of the
creation process won't benefit too because I'll need to do it in every
project again.

Why not do it the simple way for all kinds of users?

1) You create the UUID on the client side

Use "new AggregateIdentifierUUID(uuidStrFromClient)" - No factory at

2) You create the UUID inside the CommandHandler

Use "new AggregateIdentifierUUID()" - No factory necessary too
(creates a random UUID ).

3) You like to incorporate your own process of creating aggregate

Use "myFactory.create()" - Provide a default UUID factory
implementation (like

This way you can make all users happy and don't have any additional

Yeah, the sample app is running a littlebit behind on implementing the best practices. I heard someone is creating a very cool full-fledged sample app, so keeping up the silly address book isn’t high enough on the priority list ;-).

I was 50/50 on the factory vs constructor, but I believe you have a valid point there. IDE’s tend to be more friendly towards constructors (just type "new " & ctrl+space to get some hints). I’ll create two implementations instead. One that uses UUID (either provided or generated), and one that allows Strings (provided only).

Maybe this is something you can move to the Axon Core code base?

Injecting the AggregateIdentifierFactory can be easily done with only
two annotation (@Inject and @IdUUID):