Class AbstractRepository<T,A extends Aggregate<T>>
- Type Parameters:
T- The type of aggregate this repository stores
- All Implemented Interfaces:
ScopeAware,Repository<T>
- Direct Known Subclasses:
LockingRepository
Repository that takes care of the dispatching of events when an aggregate is
persisted. All uncommitted events on an aggregate are dispatched when the aggregate is saved.
Note that this repository implementation does not take care of any locking. The underlying persistence is expected
to deal with concurrency. Alternatively, consider using the LockingRepository.
- Since:
- 0.1
- Author:
- Allard Buijze
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classAbstract Builder class to instantiateAbstractRepositoryimplementations. -
Field Summary
Fields -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedAbstractRepository(AbstractRepository.Builder<T> builder) Instantiate aAbstractRepositorybased on the fields contained in theAbstractRepository.Builder. -
Method Summary
Modifier and TypeMethodDescriptionprotected AggregateModel<T> Returns the aggregate model stored by this repository.booleancanResolve(ScopeDescriptor scopeDescription) Check whether this implementation can resolve aScopeobject based on the providedscopeDescription.protected abstract AdoCreateNew(Callable<T> factoryMethod) Creates a new aggregate instance using the givenfactoryMethod.protected abstract voidRemoves the aggregate from the repository.protected abstract ALoads and initialized the aggregate with the given aggregateIdentifier.protected AdoLoadOrCreate(String aggregateIdentifier, Callable<T> factoryMethod) Loads an aggregate from the reporsitory.protected abstract voidPerforms the actual saving of the aggregate.Returns the aggregate type stored by this repository.Load the aggregate with the given unique identifier.Load the aggregate with the given unique identifier.loadOrCreate(String aggregateIdentifier, Callable<T> factoryMethod) Loads an aggregate from the repository.managedAggregates(UnitOfWork<?> uow) Returns the map of aggregates currently managed by this repository under the given unit of work.newInstance(Callable<T> factoryMethod) Creates a new managed instance for the aggregate, using the givenfactoryMethodto instantiate the aggregate's root.Creates a new managed instance for the aggregate, using the givenfactoryMethodto instantiate the aggregate's root, and then applying theinitMethodconsumer to it to perform additional initialization.protected voidpostDelete(A aggregate) Perform action that needs to be done directly after deleting an aggregate and committing the aggregate's uncommitted events.protected voidPerform action that needs to be done directly after updating an aggregate and committing the aggregate's uncommitted events.protected voidprepareForCommit(A aggregate) Register handlers with the current Unit of Work that save or delete the givenaggregatewhen the Unit of Work is committed.protected voidreportIllegalState(A aggregate) Invoked when an the givenaggregateinstance has been detected that has been part of a rolled back Unit of Work.voidsend(Message<?> message, ScopeDescriptor scopeDescription) protected voidvalidateOnLoad(Aggregate<T> aggregate, Long expectedVersion) Checks the aggregate for concurrent changes.
-
Field Details
-
spanFactory
-
-
Constructor Details
-
AbstractRepository
Instantiate aAbstractRepositorybased on the fields contained in theAbstractRepository.Builder.The provided Builder's main goal is to build an
AggregateModelspecifying genericTas the aggregate type to be stored. All aggregates in this repository must beinstanceOfthis aggregate type. To instantiate this AggregateModel, either anAggregateModelcan be provided directly or anaggregateTypeof typeClasscan be used. The latter will internally resolve to an AggregateModel. Thus, either the AggregateModel or theaggregateTypeshould be provided. AnAxonConfigurationExceptionis thrown if this criteria is not met.- Parameters:
builder- theAbstractRepository.Builderused to instantiate aAbstractRepositoryinstance
-
-
Method Details
-
newInstance
Description copied from interface:RepositoryCreates a new managed instance for the aggregate, using the givenfactoryMethodto instantiate the aggregate's root.- Specified by:
newInstancein interfaceRepository<T>- Parameters:
factoryMethod- The method to create the aggregate's root instance- Returns:
- an Aggregate instance describing the aggregate's state
- Throws:
Exception- when the factoryMethod throws an exception
-
newInstance
public A newInstance(@Nonnull Callable<T> factoryMethod, @Nonnull Consumer<Aggregate<T>> initMethod) throws Exception Description copied from interface:RepositoryCreates a new managed instance for the aggregate, using the givenfactoryMethodto instantiate the aggregate's root, and then applying theinitMethodconsumer to it to perform additional initialization.- Specified by:
newInstancein interfaceRepository<T>- Parameters:
factoryMethod- The method to create the aggregate's root instanceinitMethod- The consumer to initialize the aggregate instance further- Returns:
- an Aggregate instance describing the aggregate's state
- Throws:
Exception- when the factoryMethod throws an exception
-
doCreateNew
Creates a new aggregate instance using the givenfactoryMethod. Implementations should assume that this method is only called if a UnitOfWork is currently active.- Parameters:
factoryMethod- The method to create the aggregate's root instance- Returns:
- an Aggregate instance describing the aggregate's state
- Throws:
Exception- when the factoryMethod throws an exception
-
load
Description copied from interface:RepositoryLoad the aggregate with the given unique identifier.- Specified by:
loadin interfaceRepository<T>- Parameters:
aggregateIdentifier- The identifier of the aggregate to loadexpectedVersion- The expected version of the loaded aggregate- Returns:
- The aggregate root with the given identifier.
- Throws:
AggregateNotFoundException- if aggregate with given id cannot be foundRuntimeException- any exception thrown by implementing classes
-
loadOrCreate
public Aggregate<T> loadOrCreate(@Nonnull String aggregateIdentifier, @Nonnull Callable<T> factoryMethod) Description copied from interface:RepositoryLoads an aggregate from the repository. If the aggregate is not found it creates the aggregate using the specifiedfactoryMethod.- Specified by:
loadOrCreatein interfaceRepository<T>- Parameters:
aggregateIdentifier- The identifier of the aggregate to loadfactoryMethod- The method to create the aggregate's root instance- Returns:
- The aggregate root with the given identifier.
-
managedAggregates
Returns the map of aggregates currently managed by this repository under the given unit of work. Note that the repository keeps the managed aggregates in the root unit of work, to guarantee each Unit of Work works with the state left by the parent unit of work.The returns map is mutable and reflects any changes made during processing.
- Parameters:
uow- The unit of work to find the managed aggregates for- Returns:
- a map with the aggregates managed by this repository in the given unit of work
-
load
Description copied from interface:RepositoryLoad the aggregate with the given unique identifier. No version checks are done when loading an aggregate, meaning that concurrent access will not be checked for.- Specified by:
loadin interfaceRepository<T>- Parameters:
aggregateIdentifier- The identifier of the aggregate to load- Returns:
- The aggregate root with the given identifier.
-
validateOnLoad
Checks the aggregate for concurrent changes. Throws aConflictingModificationExceptionwhen conflicting changes have been detected.This implementation throws a
ConflictingAggregateVersionExceptionif the expected version is not null and the version number of the aggregate does not match the expected version- Parameters:
aggregate- The loaded aggregateexpectedVersion- The expected version of the aggregate- Throws:
ConflictingModificationException- when conflicting changes have been detectedConflictingAggregateVersionException- the expected version is notnulland the version number of the aggregate does not match the expected version
-
prepareForCommit
Register handlers with the current Unit of Work that save or delete the givenaggregatewhen the Unit of Work is committed.- Parameters:
aggregate- The Aggregate to save or delete when the Unit of Work is committed
-
reportIllegalState
Invoked when an the givenaggregateinstance has been detected that has been part of a rolled back Unit of Work. This typically means that the state of the Aggregate instance has been compromised and cannot be guaranteed to be correct.This implementation throws an exception, effectively causing the unit of work to be rolled back. Subclasses that can guarantee correct storage, even when specific instances are compromised, may override this method to suppress this exception.
When this method is invoked, the
doSave(Aggregate),doDelete(Aggregate),postSave(Aggregate)andpostDelete(Aggregate)are not invoked. Implementations may choose to invoke these methods.- Parameters:
aggregate- The aggregate instance with illegal state
-
aggregateModel
Returns the aggregate model stored by this repository.- Returns:
- the aggregate model stored by this repository
-
getAggregateType
Returns the aggregate type stored by this repository.- Returns:
- the aggregate type stored by this repository
-
doSave
Performs the actual saving of the aggregate.- Parameters:
aggregate- the aggregate to store
-
doLoad
Loads and initialized the aggregate with the given aggregateIdentifier.- Parameters:
aggregateIdentifier- the identifier of the aggregate to loadexpectedVersion- The expected version of the aggregate to load- Returns:
- a fully initialized aggregate
- Throws:
AggregateNotFoundException- if the aggregate with given identifier does not exist
-
doLoadOrCreate
Loads an aggregate from the reporsitory. If the aggregate does not exists, it is created using thefactoryMethod.- Parameters:
aggregateIdentifier- the identifier of the aggregatefactoryMethod- the method that creates a new instance- Returns:
- the aggregate
- Throws:
Exception- when loading or creating the aggregate failed
-
doDelete
Removes the aggregate from the repository. Typically, the repository should ensure that any calls todoLoad(String, Long)throw aAggregateNotFoundExceptionwhen loading a deleted aggregate.- Parameters:
aggregate- the aggregate to delete
-
postSave
Perform action that needs to be done directly after updating an aggregate and committing the aggregate's uncommitted events. No op by default.- Parameters:
aggregate- The aggregate instance being saved
-
postDelete
Perform action that needs to be done directly after deleting an aggregate and committing the aggregate's uncommitted events. No op by default.- Parameters:
aggregate- The aggregate instance being saved
-
send
public void send(@Nonnull Message<?> message, @Nonnull ScopeDescriptor scopeDescription) throws Exception Description copied from interface:ScopeAware- Specified by:
sendin interfaceScopeAware- Parameters:
message- aMessageto be send to aScopescopeDescription- aDextendingScopeDescriptor, describing theScopeto send the givenmessageto- Throws:
Exception- if sending themessagefailed. Might occur if the message handling process throws an exception
-
canResolve
Description copied from interface:ScopeAwareCheck whether this implementation can resolve aScopeobject based on the providedscopeDescription. Will returntruein case it should be able to resolve the Scope andfalseif it cannot.- Specified by:
canResolvein interfaceScopeAware- Parameters:
scopeDescription- aScopeDescriptordescribing theScopeto be resolved- Returns:
truein case it should be able to resolve the Scope andfalseif it cannot
-