Using the same POJO for Aggregate, Command, Event, and the DTO if the REST API in front?

Dear all,

First of all, thanks a lot for this awesome framework!! It makes CQRS/ES definitely easier to approach!! Now working with 3.0-RC1.

I have the following design question.

Let’s say I have an aggregate that is defined by three classes, as depicted below. Not that complex, but not limited to the basic case of an aggregate with one single string attribute.

I use the standard components to build my software

  • Spring Controller in front (HTTP API)
  • Command (Axon)
  • Aggregate (Axon)
  • Event (Axon)

as depicted below:

In order to avoid duplicating A,B,C, I would like to use them everywhere (as highligted in my drawing).

  • My front end in Angular is able to build something like A->B->C that can be passed directly to the REST API. So I want to use it as a parameter of the REST API (Spring Controller).
  • In the create command, I just want to forward the object to be created, that I received from the Spring Controller
  • For the aggregate, I want the A->B->C model. I started from there: it is how I designed my aggregate.
  • For the “Aggreate A was created” event, I also want to transport A.

I could re-use the aggregate classes everywhere, but then I expose all business methods in places where they should not be seen. It also obliges me to include all dependencies of that java code - any jar I could have used for implementation. I also want to avoid propagating Axon classes (annotation, etc) everywhere.

Another option would be to generate these classes from the aggregate, and write boiler plate copy that does deep copy (but that is cumbersome).

Isn’t there an option to move

  • the definition of the aggregate identifier (@AggregateIdentifier),
  • the @EventSourcingHandler,
  • the @CommandHandler on constructor for creation
    to a separate ‘service’ class?

What is your point of view on that?

(I hope I was able to make it clear)

I would really appreciate your feedback on that.
Thanks a lot,
Octave

Hi,

What you want makes a lot of sense (if I understood your question :).

However, it should not be the aggregate instance that’s shared within your application but rather the state of the aggregate. The aggregate itself still functions as the component that handles commands and updates the state (by applying events). The state of the aggregate however is then simply a value object that is updated by events. Note that it makes sense to make the aggregate state immutable while the aggregate itself is mutable (since its internal aggregate state changes with each event).

The initial state ABC can then be safely passed to the aggregate via a create command.

Rene