Aggregate

public abstract class Aggregate<I, S extends EntityState, B extends ValidatingBuilder<S>> extends CommandHandlingEntity<I, S, B> implements EventPlayer, EventReactor

Abstract base for aggregates.

An aggregate is the main building block of a business model. Aggregates guarantee consistency of data modifications in response to commands they receive.

An aggregate modifies its state in response to a command and produces one or more events. These events are used later to restore the state of the aggregate.

Creating an aggregate class

To create a new aggregate class:

  1. Select a type for identifiers of the aggregate. If you select to use a typed identifier (which is recommended), define a protobuf message for the ID type.
  2. Define the structure of the aggregate state as a Protobuf message.
  3. Generate Java code for ID and state types.
  4. Create new Java class derived from Aggregate passing ID and state types as generic parameters.

Adding command handler methods

Command handling methods of an Aggregate are defined in the same way as described in CommandHandlingEntity.

Event(s) returned by command handling methods are posted to the EventBus automatically by AggregateRepository.

Adding event applier methods

Aggregate data is stored as a sequence of events it produces. The state of the aggregate is restored by re-playing the history of events and invoking corresponding event applier methods.

An event applier is a method that changes the state of the aggregate in response to an event. An event applier takes a single parameter of the event message it handles and returns void.

The modification of the state is done using a builder instance obtained from builder. All changes to state become reflected in state(), after all events (obtained from aggregate's history when loading an aggregate, or emitted by command handlers during the command dispatching) are played.

End-users must not call state() method within an event applier. It is so, because event appliers are invoked in scope of an active transaction, which accumulates the model updates in aggregate's builder(), and not in state(). Therefore, state() invocation from the applier's code may return some inconsistent result, and in general is prone to errors. All such attempts will result in a RuntimeException.

An Aggregate class must have applier methods for all types of the events that it produces.

Performance considerations

To improve performance of loading aggregates, an AggregateRepository periodically stores aggregate snapshots. See setSnapshotTrigger for details.

Parameters

<I>

the type for IDs of this class of aggregates

<S>

the type of the state held by the aggregate

<B>

the type of the aggregate state builder

Inheritors

Constructors

Link copied to clipboard
protected void Aggregate()
Creates a new instance.
protected void Aggregate(I id)
Creates a new instance.

Inherited properties

Link copied to clipboard
public volatile LifecycleFlags lifecycleFlags
The lifecycle flags of the entity.

Functions

Link copied to clipboard
protected final B builder()
Obtains the instance of the state builder.
Link copied to clipboard
protected final void clearRecentHistory()
Clears #recentHistory() recent history.
Link copied to clipboard
protected DispatchOutcome dispatchCommand(CommandEnvelope command)
Obtains a method for the passed command and invokes it.
Link copied to clipboard
protected void ensureAccessToState()
Prohibits invoking state() method from within an applier method.
Link copied to clipboard
protected final Iterator<Event> historyBackward()
Creates an iterator of the aggregate event history with reverse traversal.
Link copied to clipboard
protected final boolean historyContains(Predicate<Event> predicate)
Verifies if the aggregate history contains an event which satisfies the passed predicate.
Link copied to clipboard
protected final String missingTxMessage()
Instructs to modify the state of an aggregate only within an event applier method.
Link copied to clipboard
protected AggregateClass<? extends Object> modelClass()
Obtains the model class.
Link copied to clipboard
public final BatchDispatchOutcome play(Iterable<Event> events)
Plays the given events against the underlying entity.
Link copied to clipboard
public ImmutableSet<EventClass> producedEvents()
Obtains classes of the events produced by this object.
Link copied to clipboard
protected final RecentHistory recentHistory()
Obtains recent history of events of this entity.
Link copied to clipboard
protected AggregateClass<? extends Object> thisClass()
Obtains model class for this aggregate.
Link copied to clipboard
protected final int versionNumber()
Obtains the version number of the entity.

Inherited functions

Link copied to clipboard
public void afterInvoke(HandlerMethod<? extends Object, ? extends Object, ? extends Object, ? extends Object> method)
A callback for a handler method invocation end.
Link copied to clipboard
public final Api at(Level logLevel)
Obtains a new fluent logging API at the given level.
Link copied to clipboard
public void beforeInvoke(HandlerMethod<? extends Object, ? extends Object, ? extends Object, ? extends Object> method)
A callback for a handler method invocation start.
Link copied to clipboard
public final boolean changed()
Determines whether the state of this entity or its lifecycle flags have been modified since this entity instance creation.
Link copied to clipboard
protected final List<ConstraintViolation> checkEntityState(S newState)
Verifies the new entity state and returns ConstraintViolations, if any.
Link copied to clipboard
protected void checkNotArchived()
Ensures that the entity is not marked as archived.
Link copied to clipboard
protected void checkNotDeleted()
Ensures that the entity is not marked as deleted.
Link copied to clipboard
protected final S defaultState()
Obtains the default state of the entity.
Link copied to clipboard
public boolean equals(Object o)
Link copied to clipboard
protected ValueMismatch expectedDefault(Message actual, Message newValue)
Creates ValueMismatch for the case of discovering a non-default value when the default value was expected by a command.
Link copied to clipboard
protected ValueMismatch expectedEmpty(String actual, String newValue)
Creates ValueMismatch for the case of discovering a non-empty value, when an empty string was expected by a command.
Link copied to clipboard
protected ValueMismatch expectedNotDefault(Message expected)
Creates a ValueMismatch for a command that wanted to clear a value, but discovered that the field already has the default value.
protected ValueMismatch expectedNotDefault(Message expected, Message newValue)
Creates a ValueMismatch for a command that wanted to change a field value, but discovered that the field has the default value.
Link copied to clipboard
protected ValueMismatch expectedNotEmpty(String expected)
Creates a ValueMismatch for a command that wanted to clear a string value but discovered that the field is already empty.
Link copied to clipboard
public static EventPlayer forTransactionOf(TransactionalEntity<? extends Object, ? extends Object, ? extends Object> entity)
Creates a transactional EventPlayer for the given entity.
Link copied to clipboard
public final LifecycleFlags getLifecycleFlags()
Obtains the current state of the entity lifecycle flags.
Link copied to clipboard
public int hashCode()
Link copied to clipboard
public I id()
Obtains the identifier of the entity.
Link copied to clipboard
public String idAsString()
Obtains ID of the entity in the string form.
Link copied to clipboard
public boolean isActive()
Verifies if any of the lifecycle attributes is set.
Link copied to clipboard
public final boolean isArchived()
Tests whether the entity is marked as archived.
Link copied to clipboard
public final boolean isDeleted()
Tests whether the entity is marked as deleted.
Link copied to clipboard
public LifecycleFlags lifecycleFlags()
Obtains current lifecycle flags.
Link copied to clipboard
public boolean lifecycleFlagsChanged()
Tells whether lifecycle flags of the entity changed since its initialization.
Link copied to clipboard
public Nothing nothing()
Obtains the io.spine.server.model.
Link copied to clipboard
public DispatchOutcome play(Event event)
Plays the given event.
Link copied to clipboard
public Any producerId()
The object identity packed into Any.
Link copied to clipboard
protected void remember(Iterable<Event> events)
Adds events to the recent history.
Link copied to clipboard
protected final void setArchived(boolean archived)
Sets archived} status flag to the passed value.
Link copied to clipboard
protected final void setDeleted(boolean deleted)
Sets deleted} status flag to the passed value.
Link copied to clipboard
protected final void setInitialState(S initialState, Version version)
Sets an initial state for the entity.
Link copied to clipboard
public final S state()
Obtains the state of the entity.
Link copied to clipboard
public String toString()
Link copied to clipboard
protected Transaction<I, ? extends TransactionalEntity<I, S, B>, S, B> tx()
Obtains the transaction used for modifying the entity.
Link copied to clipboard
protected ValueMismatch unexpectedValue(Message expected, Message actual, Message newValue)
Creates ValueMismatch for the case of discovering a value different than by a command.
protected ValueMismatch unexpectedValue(String expected, String actual, String newValue)
Creates ValueMismatch for the case of discovering a value different than expected by a command.
Link copied to clipboard
public Version version()
Obtains the version of the entity.
Link copied to clipboard
public Timestamp whenModified()
Obtains timestamp of the entity version.