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
  • Constructor Details

  • Method Details

    • doCreateNew

      protected LockAwareAggregate<T,A> doCreateNew(Callable<T> factoryMethod) throws Exception
      Description copied from class: AbstractRepository
      Creates a new aggregate instance using the given factoryMethod. Implementations should assume that this method is only called if a UnitOfWork is currently active.
      Specified by:
      doCreateNew in class AbstractRepository<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

      protected abstract A doCreateNewForLock(Callable<T> factoryMethod) throws Exception
      Creates a new aggregate instance using the given factoryMethod. 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

      protected LockAwareAggregate<T,A> doLoad(String aggregateIdentifier, Long expectedVersion)
      Perform the actual loading of an aggregate. The necessary locks have been obtained.
      Specified by:
      doLoad in class AbstractRepository<T,LockAwareAggregate<T,A extends Aggregate<T>>>
      Parameters:
      aggregateIdentifier - the identifier of the aggregate to load
      expectedVersion - 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: AbstractRepository
      Loads an aggregate from the reporsitory. If the aggregate does not exists, it is created using the factoryMethod.
      Overrides:
      doLoadOrCreate in class AbstractRepository<T,LockAwareAggregate<T,A extends Aggregate<T>>>
      Parameters:
      aggregateIdentifier - the identifier of the aggregate
      factoryMethod - the method that creates a new instance
      Returns:
      the aggregate
      Throws:
      Exception - when loading or creating the aggregate failed
    • prepareForCommit

      protected void prepareForCommit(LockAwareAggregate<T,A> aggregate)
      Description copied from class: AbstractRepository
      Register handlers with the current Unit of Work that save or delete the given aggregate when the Unit of Work is committed.
      Overrides:
      prepareForCommit in class AbstractRepository<T,LockAwareAggregate<T,A extends Aggregate<T>>>
      Parameters:
      aggregate - The Aggregate to save or delete when the Unit of Work is committed
    • doSave

      protected void doSave(LockAwareAggregate<T,A> aggregate)
      Verifies whether all locks are valid and delegates to doSaveWithLock(Aggregate) to perform actual storage.
      Specified by:
      doSave in class AbstractRepository<T,LockAwareAggregate<T,A extends Aggregate<T>>>
      Parameters:
      aggregate - the aggregate to store
    • doDelete

      protected final void doDelete(LockAwareAggregate<T,A> aggregate)
      Verifies whether all locks are valid and delegates to doDeleteWithLock(Aggregate) to perform actual deleting.
      Specified by:
      doDelete in class AbstractRepository<T,LockAwareAggregate<T,A extends Aggregate<T>>>
      Parameters:
      aggregate - the aggregate to delete
    • doSaveWithLock

      protected abstract void doSaveWithLock(A aggregate)
      Perform the actual saving of the aggregate. All necessary locks have been verified.
      Parameters:
      aggregate - the aggregate to store
    • doDeleteWithLock

      protected abstract void doDeleteWithLock(A aggregate)
      Perform the actual deleting of the aggregate. All necessary locks have been verified.
      Parameters:
      aggregate - the aggregate to delete
    • doLoadWithLock

      protected abstract A doLoadWithLock(String aggregateIdentifier, Long expectedVersion)
      Loads the aggregate with the given aggregateIdentifier. All necessary locks have been obtained.
      Parameters:
      aggregateIdentifier - the identifier of the aggregate to load
      expectedVersion - The expected version of the aggregate to load
      Returns:
      a fully initialized aggregate
      Throws:
      AggregateNotFoundException - if the aggregate with given identifier does not exist