Class AggregateRoot<ID,EVENT_TYPE extends Event<ID>,AGGREGATE_TYPE extends AggregateRoot<ID,EVENT_TYPE,AGGREGATE_TYPE>>

java.lang.Object
dk.cloudcreate.essentials.components.eventsourced.aggregates.stateful.classic.AggregateRoot<ID,EVENT_TYPE,AGGREGATE_TYPE>
Type Parameters:
ID - the aggregate id type
EVENT_TYPE - the type of event
AGGREGATE_TYPE - the aggregate self type (i.e. your concrete aggregate type)
All Implemented Interfaces:
Aggregate<ID,AGGREGATE_TYPE>, StatefulAggregate<ID,EVENT_TYPE,AGGREGATE_TYPE>
Direct Known Subclasses:
AggregateRootWithState

public abstract class AggregateRoot<ID,EVENT_TYPE extends Event<ID>,AGGREGATE_TYPE extends AggregateRoot<ID,EVENT_TYPE,AGGREGATE_TYPE>> extends Object implements StatefulAggregate<ID,EVENT_TYPE,AGGREGATE_TYPE>
A specialized and opinionated mutable Aggregate design
This AggregateRoot is designed to work with Class based Event's that inherit from Event.
This design is deliberate and will manage a lot of things for you as a developer at the cost of some flexibility.

Specifically you only have to supply the Aggregate ID, through Event.aggregateId(), on the FIRST/initial Event that's being applied to the AggregateRoot using the apply(Event) method.
Every consecutive Event applied will automatically have its Event.aggregateId(Object) method called IF it doesn't already have a value.
I.e. you can be lazy and skip setting the aggregate id on the Event if you don't want to.
The AggregateRoot also automatically keeps track of the Event.eventOrder() value and will set it for you and ensure that it's consecutively growing.

Note: The AggregateRoot works best in combination with the StatefulAggregateRepository

You don't have to use the AggregateRoot IF it doesn't fit your purpose. It's always possible to build your own Aggregate concept.

See Also:
  • Constructor Details

    • AggregateRoot

      public AggregateRoot()
  • Method Details

    • initialize

      protected void initialize()
      Initialize the aggregate, e.g. setting up state objects, PatternMatchingMethodInvoker, etc.
    • rehydrate

      public AGGREGATE_TYPE rehydrate(dk.cloudcreate.essentials.components.eventsourced.eventstore.postgresql.eventstream.AggregateEventStream<ID> persistedEvents)
      Effectively performs a leftFold over all the previously persisted events related to this aggregate instance
      Specified by:
      rehydrate in interface Aggregate<ID,EVENT_TYPE extends Event<ID>>
      Parameters:
      persistedEvents - the previous persisted events related to this aggregate instance, aka. the aggregates history
      Returns:
      the same aggregate instance (self)
    • rehydrate

      public AGGREGATE_TYPE rehydrate(Stream<EVENT_TYPE> previousEvents)
      Effectively performs a leftFold over all the previous events related to this aggregate instance
      Parameters:
      previousEvents - the previous events related to this aggregate instance, aka. the aggregates history
      Returns:
      the same aggregate instance (self)
    • eventOrderOfLastRehydratedEvent

      public dk.cloudcreate.essentials.components.eventsourced.eventstore.postgresql.types.EventOrder eventOrderOfLastRehydratedEvent()
      Description copied from interface: Aggregate
      Get the eventOrder of the last event during aggregate hydration (using the Aggregate.rehydrate(AggregateEventStream) method)
      Specified by:
      eventOrderOfLastRehydratedEvent in interface Aggregate<ID,EVENT_TYPE extends Event<ID>>
      Returns:
      the event order of the last applied Event or EventOrder.NO_EVENTS_PREVIOUSLY_PERSISTED in case no events has ever been applied to the aggregate
    • apply

      protected void apply(EVENT_TYPE event)
      Apply a new non persisted/uncommitted Event to this aggregate instance.
      If it is the very FIRST Event that is being applied then Event.aggregateId() MUST return the ID of the aggregate the event relates to
      Every consecutive Event applied will have its Event.aggregateId(Object) method called IF it doesn't already have a value. I.e. you can be lazy and skip setting the aggregate id on the Event if you don't want to.

      The AggregateRoot automatically keeps track of the Event.eventOrder() value and will set it for you and ensure that it's growing consecutively.

      Parameters:
      event - the event to apply
    • aggregateId

      public ID aggregateId()
      Description copied from interface: Aggregate
      The id of the aggregate (aka. the stream-id)
      Specified by:
      aggregateId in interface Aggregate<ID,EVENT_TYPE extends Event<ID>>
    • hasBeenRehydrated

      public boolean hasBeenRehydrated()
      Specified by:
      hasBeenRehydrated in interface Aggregate<ID,EVENT_TYPE extends Event<ID>>
    • isRehydrating

      protected final boolean isRehydrating()
      Is the event being supplied to applyEventToTheAggregateState(Event) a previously persisted (i.e. a historic event)
    • applyEventToTheAggregateState

      protected void applyEventToTheAggregateState(Event<ID> event)
      Apply the event to the aggregate instance to reflect the event as a state change to the aggregate
      The default implementation will automatically call any (private) methods annotated with EventHandler
      Parameters:
      event - the event to apply to the aggregate
      See Also:
    • eventOrderOfLastAppliedEvent

      public dk.cloudcreate.essentials.components.eventsourced.eventstore.postgresql.types.EventOrder eventOrderOfLastAppliedEvent()
      Returns:
      the event order of the last applied Event or EventOrder.NO_EVENTS_PREVIOUSLY_PERSISTED in case no events has ever been applied to the aggregate
    • getUncommittedChanges

      public EventsToPersist<ID,EVENT_TYPE> getUncommittedChanges()
      The the events that have been applied to this aggregate instance but not yet persisted to the underlying EventStore
      Specified by:
      getUncommittedChanges in interface StatefulAggregate<ID,EVENT_TYPE extends Event<ID>,AGGREGATE_TYPE extends AggregateRoot<ID,EVENT_TYPE,AGGREGATE_TYPE>>
      Returns:
      the changes to the aggregate
    • markChangesAsCommitted

      public void markChangesAsCommitted()
      Resets the getUncommittedChanges() - effectively marking them as having been persisted and committed to the underlying EventStore
      Specified by:
      markChangesAsCommitted in interface StatefulAggregate<ID,EVENT_TYPE extends Event<ID>,AGGREGATE_TYPE extends AggregateRoot<ID,EVENT_TYPE,AGGREGATE_TYPE>>