Class LockingSagaRepository<T>
- All Implemented Interfaces:
SagaRepository<T>
- Direct Known Subclasses:
AnnotatedSagaRepository
The lock is obtained before the saga is loaded or created and held until the ProcessingContext completes, so
only one processing context at a time operates on a given saga.
The default PessimisticLockFactory hands out a lock owned by the thread that acquired it, which means the
lock must be released on that same thread. Axon Framework 4 got that for free, because the unit of work was bound to
the thread through a thread local. In Axon Framework 5 it holds when the ProcessingContext runs its
completion handlers on the invoking thread, which is what a TransactionManager answering true to
requiresSameThreadInvocations() arranges. Both SpringTransactionManager and
EntityManagerTransactionManager do. Without one, the release can happen on another thread, the lock is never
released, and the saga becomes permanently unreachable; that failure is logged as an error naming the saga and both
threads, since nothing can recover the lock at that point. A saga repository therefore needs a transaction manager
that requires same-thread invocations, in the same way JdbcSagaStore needs a transaction-aware
ConnectionProvider.
- Since:
- 3.0
- Author:
- Rene de Waele
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classAbstract Builder class to instantiateLockingSagaRepositoryimplementations. -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedInstantiate aLockingSagaRepositorybased on the fields contained in theLockingSagaRepository.Builder. -
Method Summary
Modifier and TypeMethodDescriptioncreateInstance(String sagaIdentifier, Supplier<T> factoryMethod, ProcessingContext context) Creates a new Saga instance.doCreateInstance(String sagaIdentifier, Supplier<T> factoryMethod, ProcessingContext context) Creates a new Saga instance.doLoad(String sagaIdentifier, ProcessingContext context) Loads a known Saga instance by its unique identifier.load(String sagaIdentifier, ProcessingContext context) Loads a known Saga instance by its unique identifier.Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface org.axonframework.modelling.saga.SagaRepository
find
-
Constructor Details
-
LockingSagaRepository
Instantiate aLockingSagaRepositorybased on the fields contained in theLockingSagaRepository.Builder.Will assert that the
LockFactoryis notnull. Will throw anAxonConfigurationExceptionif it is.- Parameters:
builder- theLockingSagaRepository.Builderused to instantiate aLockingSagaRepositoryinstance
-
-
Method Details
-
load
Loads a known Saga instance by its unique identifier. Due to the concurrent nature of Sagas, it is not unlikely for a Saga to have ceased to exist after it has been found based on associations. Therefore, a repository should returnnullin case a Saga doesn't exists, as opposed to throwing an exception.This implementation locks access to sagas with the given
sagaIdentifierand releases the lock when the givencontextcompletes, on both commit and rollback.- Specified by:
loadin interfaceSagaRepository<T>- Parameters:
sagaIdentifier- The unique identifier of the Saga to loadcontext- theProcessingContextthe loaded Saga is managed in- Returns:
- The Saga instance, or
nullif no such saga exists
-
createInstance
public Saga<T> createInstance(String sagaIdentifier, Supplier<T> factoryMethod, ProcessingContext context) Creates a new Saga instance. The returned Saga will delegate event handling to the instance supplied by the givenfactoryMethod.This implementation locks access to sagas with the given
sagaIdentifierand releases the lock when the givencontextcompletes, on both commit and rollback.- Specified by:
createInstancein interfaceSagaRepository<T>- Parameters:
sagaIdentifier- the identifier to use for the new saga instancefactoryMethod- Used to create a new Saga delegatecontext- theProcessingContextthe new Saga is managed in- Returns:
- a new Saga instance wrapping an instance of type
T
-
doLoad
Loads a known Saga instance by its unique identifier. Due to the concurrent nature of Sagas, it is not unlikely for a Saga to have ceased to exist after it has been found based on associations. Therefore, a repository should returnnullin case a Saga doesn't exists, as opposed to throwing an exception.- Parameters:
sagaIdentifier- The unique identifier of the Saga to loadcontext- theProcessingContextthe loaded Saga is managed in- Returns:
- The Saga instance, or
nullif no such saga exists
-
doCreateInstance
protected abstract Saga<T> doCreateInstance(String sagaIdentifier, Supplier<T> factoryMethod, ProcessingContext context) Creates a new Saga instance. The returned Saga will delegate event handling to the instance supplied by the givenfactoryMethod.- Parameters:
sagaIdentifier- the identifier to use for the new saga instancefactoryMethod- Used to create a new Saga delegatecontext- theProcessingContextthe new Saga is managed in- Returns:
- a new Saga instance wrapping an instance of type
T
-