Class AggregateRoot<ID,​EVENT_TYPE extends Event<ID>,​AGGREGATE_TYPE extends 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:
    AggregateRootWithState
    • Constructor Detail

      • AggregateRoot

        public AggregateRoot()
    • Method Detail

      • 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
      • 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:
        isRehydrating()