One to many relationship between ARs

Hello,

I have rather CQRS related question than axon related, but maybe you can give me some tip.

I have two ARs, let’s say A and B, which have one to many relationship

  • A define some settings (for example, minimal/maximal value etc…)
  • B store some value which must satisfy settings of A

So, there can be a lot of B’s which are “bound” to some A.

I have following commands and events:

CreateaA(aId, min, max)
-> ACreated(aId, min, max)

ChangeA(aId, min, max)
-> AChanged(aId, min, max)

CreateB(bId, aId, initialValue)
BCreated(bId, aId, initialValue, min, max)

  1. How should CreateB command be handled? Should i use A read model inside handler to find A aggregate, get its settings and apply BCreated event?

  2. Also I want to notify all B instances if A’s settings is changed … this can be solved by saga, which listen for AChanged event and then using read model gets all B ids and
    send commands to update settings of all B instances, right?

I know that A aggregate root is a simple CRUD and can be implemented that way and only publish events, but that doesn’t matter now. There can be better examples, but I wonder how
should I share data between ARs? Should I pass IDs in commands, load instances using read model in command handlers and pass that data to events? Is there any better way?

NOTE: A and B cannot be in same aggregate.

Hi,

for your first point (the creation), I see two patterns being used.
The first is to have A raise an event when it has “agreed” to have a specific B created. A Saga will start and send a command to create B. That Saga can then also be used to update A of changes in B and vice versa.
The other option is, as you said, use a query model to set certain information in B when it is created.
You’d choose your option depending on whether stale data is a problem and/or the creation of B involves business rules that logically belong to A.

Cheers,

Allard

Hello,

I tried to think more about that problem and probably use option 2 (using read model), because:

Aggregate root A will not be changed very much, so the risk that it returns stale data is very low. Also when it occasionally changes, some event handler sends commands to update settings to all B’s. It will be slow operation, but it will not occur many times.

I also plan to model A bounded context with CRUD, because there is no business rules and use cases, it is there only for defining settings…

How can I change CQRS model to CRUD model in axon?

I need to remove commands and command handlers and create service with methods instead.

a) Should service persist changes to “read” model immediately and then publish events to event bus (to notify other BCs), or

b) should service only publish events to event bus and there should still be event listeners for projection (to update read model) as in CQRS

I think a) should work without any problem, right?

Dne pondělí 3. srpna 2015 14:47:27 UTC+2 Allard Buijze napsal(a):

Hi,

if you want to use a object-relationally stored model (supposing that’s what you mean with crud model), you can still use commands and events. The only thing is that the repository is of a different type, and will store the aggregate’s current state in a table. Just the way regular ORM does it. Your queries can (in most cases) use the same table. You can use the GenericJpaRepository in that case.

In cases where you don’t use event sourcing, you need to define which changes in your aggregate you want to be notified as events. You don’t need to define an event for every state change.

Cheers,

Allard

Hi Allard,

I think I am facing a similar situation. We have a primary model that supports CRUD and should be used for (consistent) read and writes. The event store is a plus.

So far I am using the HybridJpaRepository and I managed to get it working correctly only after much struggle with hibernate and cascading of (delete) operations.

The next time I’d much rather have an event handler to update the database from events, using one or more entity-specific repositories. These entity repos would be Spring beans, parameter injected in the the aggregate event handlers when necessary to travel relations to observe current state.

The question then is: is it possible to have an event handler work in the same transaction as the aggregate, while other can still be asynchronous and events are distributed via the AMQP terminal?

Thanks

Hi,

yes, it’s possible, but not with standard components. What you’d have to do, is implement the EventBusTerminal interface that delegates to two instances, and forward the onClusterCreated method to either a SimpleTerminal or an AMQPTerminal. All events should be forwarded to both.
Clusters attached to the SimpleTerminal will forward event in the same thread, allowing you to use the same transaction.

Hope that helps.
Cheers,

Allard