Simple "CRUD" read on Axon aggregate

Viewed 82

What's the simplest way to do a basic GET on the Aggregate in a REST-Axon program, without AxonServer?

  • I have a simple springboot Axon-and-REST application with an aggregate FooAggregate.
  • I create the Foo with a POST /foos which send a command on the command gateway, etc.
  • I query the list of all Foos by actually querying GET /foo-summaries, which fires query objects on the query gateway, and returns where FooSummary objects, where FooSummary is a JPA entity I create in a projection that listens to FooCreated and FooUpdated events.

All standard stuff so far. But what about simple GET /foos/{id} ?

That URL /foo/{id} is what I want to return in the Location header from POST /foos And I want this GET to return all of the details of my Foo - all of which are modeled as properties of the FooAggregate (the FooSummary might return a subset for listing)

Now, Axon documentation suggests this:

Standard repositories store the actual state of an Aggregate. Upon each change, the new state will overwrite the old. This makes it possible for the query components of the application to use the same information the command component also uses. This could, depending on the type of application you are creating, be the simplest solution.

But that only applies if I use state-stored aggregates, right? I'm using Event-Sourced aggregates, with a JPA eventstore.

My options would appear to be:

  1. Forget about the event-sourcing and use the stored-state aggregate approach, as suggested as being the 'simplest' approach (I don't have any specific need to event source my aggregate - although I am definitely event sourcing my projection(s)

  2. Keep the full details in my FooSummary projection table, and direct GET /foo/{id} to there with a slightly different query than GET /foo-summaries (alternative, just call it GET /foos and return summaries)

  3. Create a separate "projection" to store the full Foo details. This would be effectively identical to what we would use in the state-stored aggregate, so it seems a little weird.

  4. Some 4th option - the reason for this question?

1 Answers

Answering my own question, but really the answer came from a discussion with Christian at Axon. (Will leave this open for a few days to allow for better answers, before accepting my own :))

My options #2 and #3 are the right answers: the difference depending on how different my "summary" projection is from my "detailed" projection. If they're close enough, option #2, if they're different enough #3.

Option #1 is non-ideal, because even if we were using state-stored for some other reason, basing queries on the state-store breaks the Segregation that is the 'S' in CQRS: it makes our query model depend on our command model, which can lead to problems when our model gets more complex.

(Thanks Christian)

Related