Class JpaSagaStore
SagaStore. It uses an EntityManager to persist the actual saga in a backing
store in serialized form.
After each operation that modified the backing store, EntityManager.flush() is invoked to ensure the store
contains the last modifications. To override this behavior, see setUseExplicitFlush(boolean)
This store manages no transaction of its own. It takes an EntityManager from the
EntityManagerProvider it was given, so its changes commit together with whatever else the surrounding
transaction covers. Give it the same provider instance the transaction manager was given, and use a provider that
resolves the EntityManager of the calling thread's transaction on every call, as a container-managed
shared-EntityManager proxy does. A fixed
SimpleEntityManagerProvider is suitable only where a single thread is involved,
such as in a test.
Such a provider finds the transaction by thread, so the store has to be called on the thread that began it. A
TransactionManager declaring requiresSameThreadInvocations() arranges that, and the ones shipped for
Spring and JPA do. A custom transaction manager that leaves that method at its default of false does not, and
neither does handler code that moves work onto a thread of its own.
Saga handling should run inside a transaction. JPA enforces that itself: without an active one these operations fail rather than write partial state.
The saga type column holds the saga class name and is matched against it. Axon Framework 4 derived both through its
Serializer, which for the default configuration also produced the class name, so an existing table reads and
writes unchanged. An application that mapped its saga classes to some other type name, an XStream alias being the
usual way, has rows this store cannot route to and must rewrite that column to the class name first.
The saga state itself is converted with the configured Converter. Axon Framework 4 defaulted to the
XStreamSerializer unless the application configured another serializer, so the stored state of such an
application is XStream XML, which a JSON-based converter cannot read: loading such a saga fails. Give this store an
XStreamConverter if you are migrating such a scenario to read that state
and to write it back in the same form, which also lets Axon Framework 4 nodes keep handling the same sagas during a
rolling upgrade.
- Since:
- 3.0
- Author:
- Allard Buijze
-
Nested Class Summary
Nested ClassesNested classes/interfaces inherited from interface org.axonframework.modelling.saga.repository.SagaStore
SagaStore.Entry<T> -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedJpaSagaStore(JpaSagaStore.Builder builder) Instantiate aJpaSagaStorebased on the fields contained in theJpaSagaStore.Builder. -
Method Summary
Modifier and TypeMethodDescriptionstatic JpaSagaStore.Builderbuilder()Instantiate a Builder to be able to create aJpaSagaStore.protected SagaEntry<?> createSagaEntry(Object saga, String sagaIdentifier, Converter converter) Intended for clients to override.voiddeleteSaga(Class<?> sagaType, String sagaIdentifier, Set<AssociationValue> associationValues) Deletes a Saga with givensagaTypeandsagaIdentifierand all its associations.findSagas(Class<?> sagaType, AssociationValue associationValue) Returns identifiers of saga instances of the givensagaTypethat have been associated with the givenassociationValue.voidinsertSaga(Class<?> sagaType, String sagaIdentifier, Object saga, Set<AssociationValue> associationValues) Adds a new Saga and its initial association values to the store.protected Set<AssociationValue> loadAssociationValues(jakarta.persistence.EntityManager entityManager, Class<?> sagaType, String sagaIdentifier) <S> @Nullable SagaStore.Entry<S> protected voidremoveAssociationValue(jakarta.persistence.EntityManager entityManager, Class<?> sagaType, String sagaIdentifier, AssociationValue associationValue) Removes the givenassociationValueof the saga with givensagaIdentifierandsagaType.protected StringIntended for clients to override.voidsetUseExplicitFlush(boolean useExplicitFlush) Sets whether or not to do an explicitEntityManager.flush()after each data modifying operation on the backing storage.protected voidstoreAssociationValue(jakarta.persistence.EntityManager entityManager, Class<?> sagaType, String sagaIdentifier, AssociationValue associationValue) Stores the givenassociationValueof the saga with givensagaIdentifierandsagaType.voidupdateSaga(Class<?> sagaType, String sagaIdentifier, Object saga, AssociationValues associationValues) Updates a given Saga after its state was modified, applying the association values added and removed since it was last stored.
-
Constructor Details
-
JpaSagaStore
Instantiate aJpaSagaStorebased on the fields contained in theJpaSagaStore.Builder.Will assert that the
EntityManagerProviderandConverterare notnull, and will throw anAxonConfigurationExceptionif any of them isnull.- Parameters:
builder- theJpaSagaStore.Builderused to instantiate aJpaSagaStoreinstance
-
-
Method Details
-
builder
Instantiate a Builder to be able to create aJpaSagaStore.The
EntityManagerProviderandConverterare hard requirements and as such should be provided.- Returns:
- a Builder to be able to create a
JpaSagaStore
-
loadSaga
Description copied from interface:SagaStoreLoads a known sagaSagaStore.Entryinstance with givensagaTypeand uniquesagaIdentifier.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 return
nullin case a Saga doesn't exists, as opposed to throwing an exception. -
loadAssociationValues
protected Set<AssociationValue> loadAssociationValues(jakarta.persistence.EntityManager entityManager, Class<?> sagaType, String sagaIdentifier) - Parameters:
entityManager- the entity manager instance to use for the querysagaType- the saga instance classsagaIdentifier- the saga identifier- Returns:
- the associations of the given saga
-
removeAssociationValue
protected void removeAssociationValue(jakarta.persistence.EntityManager entityManager, Class<?> sagaType, String sagaIdentifier, AssociationValue associationValue) Removes the givenassociationValueof the saga with givensagaIdentifierandsagaType.- Parameters:
entityManager- the entity manager instance to use for the querysagaType- the saga instance classsagaIdentifier- the saga identifierassociationValue- the association value to remove
-
storeAssociationValue
protected void storeAssociationValue(jakarta.persistence.EntityManager entityManager, Class<?> sagaType, String sagaIdentifier, AssociationValue associationValue) Stores the givenassociationValueof the saga with givensagaIdentifierandsagaType.- Parameters:
entityManager- the entity manager instance to use for the querysagaType- the saga instance classsagaIdentifier- the saga identifierassociationValue- the association value to add
-
findSagas
Description copied from interface:SagaStoreReturns identifiers of saga instances of the givensagaTypethat have been associated with the givenassociationValue. -
deleteSaga
public void deleteSaga(Class<?> sagaType, String sagaIdentifier, Set<AssociationValue> associationValues) Description copied from interface:SagaStoreDeletes a Saga with givensagaTypeandsagaIdentifierand all its associations. For convenience all known association values are passed along as well, which has the advantage that the saga store is not required to keep an index of association value to saga identifier.- Specified by:
deleteSagain interfaceSagaStore<Object>- Parameters:
sagaType- The type of saga to deletesagaIdentifier- The identifier of the saga to deleteassociationValues- The known associations of the saga
-
updateSaga
public void updateSaga(Class<?> sagaType, String sagaIdentifier, Object saga, AssociationValues associationValues) Description copied from interface:SagaStoreUpdates a given Saga after its state was modified, applying the association values added and removed since it was last stored.- Specified by:
updateSagain interfaceSagaStore<Object>- Parameters:
sagaType- The type of the SagasagaIdentifier- The identifier of the Sagasaga- The Saga instanceassociationValues- The association values of the Saga, carrying the additions and removals to apply
-
insertSaga
public void insertSaga(Class<?> sagaType, String sagaIdentifier, Object saga, Set<AssociationValue> associationValues) Description copied from interface:SagaStoreAdds a new Saga and its initial association values to the store.- Specified by:
insertSagain interfaceSagaStore<Object>- Parameters:
sagaType- The type of the SagasagaIdentifier- The identifier of the Sagasaga- The Saga instanceassociationValues- The initial association values of the Saga
-
setUseExplicitFlush
public void setUseExplicitFlush(boolean useExplicitFlush) Sets whether or not to do an explicitEntityManager.flush()after each data modifying operation on the backing storage. Default totrue- Parameters:
useExplicitFlush-trueto force flush,falseotherwise.
-
createSagaEntry
Intended for clients to override. Defaults toSagaEntry.- Parameters:
saga- The Saga instancesagaIdentifier- The identifier of the Sagaconverter- the converter used to convert the saga to the form stored inSagaEntry.getSerializedSaga()- Returns:
- An instanceof @
SagaEntry
-
sagaEntryEntityName
Intended for clients to override. Defaults to 'SagaEntry'.- Returns:
- the name of the Jpa event entity
-