Class LockingRepository<T,A extends Aggregate<T>>
java.lang.Object
org.axonframework.modelling.command.AbstractRepository<T,LockAwareAggregate<T,A>>
org.axonframework.modelling.command.LockingRepository<T,A>
- Type Parameters:
T- The type that this aggregate stores
- All Implemented Interfaces:
ScopeAware,Repository<T>
- Direct Known Subclasses:
EventSourcingRepository,GenericJpaRepository,GenericJpaRepository
public abstract class LockingRepository<T,A extends Aggregate<T>>
extends AbstractRepository<T,LockAwareAggregate<T,A>>
Implementation of the Repository interface that takes provides a locking mechanism to prevent concurrent
modifications of persisted aggregates. Unless there is a locking mechanism present in the underlying persistence
environment, it is recommended to use a LockingRepository (or one of its subclasses).
The LockingRepository can be initialized with a locking strategy. Pessimistic Locking is the default
strategy. Pessimistic Locking requires an exclusive lock to be handed to a thread loading an aggregate before the
aggregate is handed over. This means that, once an aggregate is loaded, it has full exclusive access to it, until it
saves the aggregate.
Important: If an exception is thrown during the saving process, any locks held are released. The calling thread may
reattempt saving the aggregate again. If the lock is available, the thread automatically takes back the lock. If,
however, another thread has obtained the lock first, a ConcurrencyException is thrown.
- Since:
- 0.3
- Author:
- Allard Buijze
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprotected static classAbstract Builder class to instantiateLockingRepositoryimplementations. -
Field Summary
Fields inherited from class org.axonframework.modelling.command.AbstractRepository
spanFactory -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedLockingRepository(LockingRepository.Builder<T> builder) Instantiate aLockingRepositorybased on the fields contained in theLockingRepository.Builder. -
Method Summary
Modifier and TypeMethodDescriptionprotected LockAwareAggregate<T, A> doCreateNew(Callable<T> factoryMethod) Creates a new aggregate instance using the givenfactoryMethod.protected abstract AdoCreateNewForLock(Callable<T> factoryMethod) Creates a new aggregate instance using the givenfactoryMethod.protected final voiddoDelete(LockAwareAggregate<T, A> aggregate) Verifies whether all locks are valid and delegates todoDeleteWithLock(Aggregate)to perform actual deleting.protected abstract voiddoDeleteWithLock(A aggregate) Perform the actual deleting of the aggregate.protected LockAwareAggregate<T, A> Perform the actual loading of an aggregate.protected LockAwareAggregate<T, A> doLoadOrCreate(String aggregateIdentifier, Callable<T> factoryMethod) Loads an aggregate from the reporsitory.protected abstract AdoLoadWithLock(String aggregateIdentifier, Long expectedVersion) Loads the aggregate with the given aggregateIdentifier.protected voiddoSave(LockAwareAggregate<T, A> aggregate) Verifies whether all locks are valid and delegates todoSaveWithLock(Aggregate)to perform actual storage.protected abstract voiddoSaveWithLock(A aggregate) Perform the actual saving of the aggregate.protected voidprepareForCommit(LockAwareAggregate<T, A> aggregate) Register handlers with the current Unit of Work that save or delete the givenaggregatewhen the Unit of Work is committed.Methods inherited from class org.axonframework.modelling.command.AbstractRepository
aggregateModel, canResolve, getAggregateType, load, load, loadOrCreate, managedAggregates, newInstance, newInstance, postDelete, postSave, reportIllegalState, send, validateOnLoad
-
Constructor Details
-
LockingRepository
Instantiate aLockingRepositorybased on the fields contained in theLockingRepository.Builder.A goal of the provided Builder is to create an
AggregateModelspecifying genericTas the aggregate type to be stored. TheSpanFactoryis defaulted to aNoOpSpanFactory. 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.Additionally, will assert that the
LockFactoryis notnull, resulting in an AxonConfigurationException if this is the case.- Parameters:
builder- theLockingRepository.Builderused to instantiate aLockingRepositoryinstance
-
-
Method Details
-
doCreateNew
Description copied from class:AbstractRepositoryCreates a new aggregate instance using the givenfactoryMethod. Implementations should assume that this method is only called if a UnitOfWork is currently active.- Specified by:
doCreateNewin classAbstractRepository<T,LockAwareAggregate<T, A extends Aggregate<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
-
doCreateNewForLock
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
-
doLoad
Perform the actual loading of an aggregate. The necessary locks have been obtained.- Specified by:
doLoadin classAbstractRepository<T,LockAwareAggregate<T, A extends Aggregate<T>>> - Parameters:
aggregateIdentifier- the identifier of the aggregate to loadexpectedVersion- The expected version of the aggregate- Returns:
- the fully initialized aggregate
- Throws:
AggregateNotFoundException- if aggregate with given id cannot be found
-
doLoadOrCreate
protected LockAwareAggregate<T,A> doLoadOrCreate(String aggregateIdentifier, Callable<T> factoryMethod) throws Exception Description copied from class:AbstractRepositoryLoads an aggregate from the reporsitory. If the aggregate does not exists, it is created using thefactoryMethod.- Overrides:
doLoadOrCreatein classAbstractRepository<T,LockAwareAggregate<T, A extends Aggregate<T>>> - 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
-
prepareForCommit
Description copied from class:AbstractRepositoryRegister handlers with the current Unit of Work that save or delete the givenaggregatewhen the Unit of Work is committed.- Overrides:
prepareForCommitin classAbstractRepository<T,LockAwareAggregate<T, A extends Aggregate<T>>> - Parameters:
aggregate- The Aggregate to save or delete when the Unit of Work is committed
-
doSave
Verifies whether all locks are valid and delegates todoSaveWithLock(Aggregate)to perform actual storage.- Specified by:
doSavein classAbstractRepository<T,LockAwareAggregate<T, A extends Aggregate<T>>> - Parameters:
aggregate- the aggregate to store
-
doDelete
Verifies whether all locks are valid and delegates todoDeleteWithLock(Aggregate)to perform actual deleting.- Specified by:
doDeletein classAbstractRepository<T,LockAwareAggregate<T, A extends Aggregate<T>>> - Parameters:
aggregate- the aggregate to delete
-
doSaveWithLock
Perform the actual saving of the aggregate. All necessary locks have been verified.- Parameters:
aggregate- the aggregate to store
-
doDeleteWithLock
Perform the actual deleting of the aggregate. All necessary locks have been verified.- Parameters:
aggregate- the aggregate to delete
-
doLoadWithLock
Loads the aggregate with the given aggregateIdentifier. All necessary locks have been obtained.- 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
-