I
- the type for IDs of this class of aggregatesS
- the type of the state held by the aggregateB
- the type of the aggregate state builderpublic abstract class Aggregate<I,S extends io.spine.base.EntityState,B extends io.spine.protobuf.ValidatingBuilder<S>> extends CommandHandlingEntity<I,S,B> implements EventReactor
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.
To create a new aggregate class:
Aggregate
passing ID and
state types as generic parameters.
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
.
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 Aggregate.builder()
.
An Aggregate
class must have applier methods for
all types of the events that it produces.
To improve performance of loading aggregates, an
AggregateRepository
periodically stores aggregate snapshots.
See AggregateRepository.setSnapshotTrigger(int)
for details.
Entity.GenericParameter
Modifier | Constructor and Description |
---|---|
protected |
Aggregate()
Creates a new instance.
|
protected |
Aggregate(I id)
Creates a new instance.
|
Modifier and Type | Method and Description |
---|---|
protected B |
builder()
Obtains the instance of the state builder.
|
protected void |
clearRecentHistory()
Clears recent history.
|
protected io.spine.server.dispatch.DispatchOutcome |
dispatchCommand(CommandEnvelope command)
Obtains a method for the passed command and invokes it.
|
protected java.util.Iterator<io.spine.core.Event> |
historyBackward()
Creates an iterator of the aggregate event history with reverse traversal.
|
protected boolean |
historyContains(java.util.function.Predicate<io.spine.core.Event> predicate)
Verifies if the aggregate history contains an event which satisfies the passed predicate.
|
protected java.lang.String |
missingTxMessage()
Instructs to modify the state of an aggregate only within an event applier method.
|
io.spine.server.dispatch.BatchDispatchOutcome |
play(java.lang.Iterable<io.spine.core.Event> events) |
protected RecentHistory |
recentHistory()
Obtains recent history of events of this entity.
|
protected AggregateClass<?> |
thisClass()
Obtains model class for this aggregate.
|
protected int |
versionNumber()
Obtains the version number of the entity.
|
expectedDefault, expectedEmpty, expectedNotDefault, expectedNotDefault, expectedNotEmpty, producerId, unexpectedValue, unexpectedValue
getLifecycleFlags, remember, setArchived, setDeleted, setInitialState, tx
afterInvoke, at, beforeInvoke, checkEntityState, checkNotArchived, checkNotDeleted, defaultState, equals, hashCode, id, idAsString, isArchived, isDeleted, lifecycleFlagsChanged, state, toString, version, whenModified
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
nothing, producedEvents, producerId, version
isActive, lifecycleFlags
protected Aggregate()
If you do have tests that create aggregates using constructors, consider annotating
them with @VisibleForTesting
. Otherwise, aggregate constructors (that are
invoked by AggregateRepository
using Reflection) may be left private
.
protected Aggregate(I id)
id
- the ID for the new aggregateIf you do have tests that create aggregates via constructors, consider annotating
them with @VisibleForTesting
. Otherwise, aggregate constructors (that are
invoked by AggregateRepository
via Reflection) may be left private
.
protected AggregateClass<?> thisClass()
thisClass
in class AbstractEntity<I,S extends io.spine.base.EntityState>
protected final B builder()
This method must be called only from within an active transaction.
In Aggregate
this method must be called only from within an event applier.
protected io.spine.server.dispatch.DispatchOutcome dispatchCommand(CommandEnvelope command)
Dispatching the commands results in emitting event messages. All the empty messages are filtered out from the result.
dispatchCommand
in class CommandHandlingEntity<I,S extends io.spine.base.EntityState,B extends io.spine.protobuf.ValidatingBuilder<S>>
command
- the envelope with the command to dispatchpublic final io.spine.server.dispatch.BatchDispatchOutcome play(java.lang.Iterable<io.spine.core.Event> events)
protected final java.lang.String missingTxMessage()
missingTxMessage
in class TransactionalEntity<I,S extends io.spine.base.EntityState,B extends io.spine.protobuf.ValidatingBuilder<S>>
protected final void clearRecentHistory()
Opens the method for the repository.
clearRecentHistory
in class TransactionalEntity<I,S extends io.spine.base.EntityState,B extends io.spine.protobuf.ValidatingBuilder<S>>
protected final RecentHistory recentHistory()
Opens the method to this package for testing.
recentHistory
in class TransactionalEntity<I,S extends io.spine.base.EntityState,B extends io.spine.protobuf.ValidatingBuilder<S>>
protected final java.util.Iterator<io.spine.core.Event> historyBackward()
The records are returned sorted by timestamp in a descending order (from newer to older).
The iterator is empty if there's no history for the aggregate.
protected final boolean historyContains(java.util.function.Predicate<io.spine.core.Event> predicate)
protected final int versionNumber()
Overrides to expose the method to the package.
versionNumber
in class AbstractEntity<I,S extends io.spine.base.EntityState>