Doc tx semantics for @TransactionalEventListener after completion phases
This commit improves the Javadoc regarding transactional semantics for @TransactionalEventListener methods invoked in the AFTER_COMMIT, AFTER_ROLLBACK, or AFTER_COMPLETION phase. Specifically, the documentation now points out that interactions with the underlying transactional resource will not be committed in those phases. Closes gh-26974
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,10 +21,11 @@ import java.util.function.Consumer;
|
||||
import org.springframework.transaction.support.TransactionSynchronization;
|
||||
|
||||
/**
|
||||
* The phase at which a transactional event listener applies.
|
||||
* The phase in which a transactional event listener applies.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 4.2
|
||||
* @see TransactionalEventListener#phase()
|
||||
* @see TransactionalApplicationListener#getTransactionPhase()
|
||||
@@ -33,35 +34,44 @@ import org.springframework.transaction.support.TransactionSynchronization;
|
||||
public enum TransactionPhase {
|
||||
|
||||
/**
|
||||
* Fire the event before transaction commit.
|
||||
* Handle the event before transaction commit.
|
||||
* @see TransactionSynchronization#beforeCommit(boolean)
|
||||
*/
|
||||
BEFORE_COMMIT,
|
||||
|
||||
/**
|
||||
* Fire the event after the commit has completed successfully.
|
||||
* <p>Note: This is a specialization of {@link #AFTER_COMPLETION} and
|
||||
* therefore executes in the same after-completion sequence of events,
|
||||
* Handle the event after the commit has completed successfully.
|
||||
* <p>Note: This is a specialization of {@link #AFTER_COMPLETION} and therefore
|
||||
* executes in the same sequence of events as {@code AFTER_COMPLETION}
|
||||
* (and not in {@link TransactionSynchronization#afterCommit()}).
|
||||
* <p>Interactions with the underlying transactional resource will not be
|
||||
* committed in this phase. See
|
||||
* {@link TransactionSynchronization#afterCompletion(int)} for details.
|
||||
* @see TransactionSynchronization#afterCompletion(int)
|
||||
* @see TransactionSynchronization#STATUS_COMMITTED
|
||||
*/
|
||||
AFTER_COMMIT,
|
||||
|
||||
/**
|
||||
* Fire the event if the transaction has rolled back.
|
||||
* <p>Note: This is a specialization of {@link #AFTER_COMPLETION} and
|
||||
* therefore executes in the same after-completion sequence of events.
|
||||
* Handle the event if the transaction has rolled back.
|
||||
* <p>Note: This is a specialization of {@link #AFTER_COMPLETION} and therefore
|
||||
* executes in the same sequence of events as {@code AFTER_COMPLETION}.
|
||||
* <p>Interactions with the underlying transactional resource will not be
|
||||
* committed in this phase. See
|
||||
* {@link TransactionSynchronization#afterCompletion(int)} for details.
|
||||
* @see TransactionSynchronization#afterCompletion(int)
|
||||
* @see TransactionSynchronization#STATUS_ROLLED_BACK
|
||||
*/
|
||||
AFTER_ROLLBACK,
|
||||
|
||||
/**
|
||||
* Fire the event after the transaction has completed.
|
||||
* Handle the event after the transaction has completed.
|
||||
* <p>For more fine-grained events, use {@link #AFTER_COMMIT} or
|
||||
* {@link #AFTER_ROLLBACK} to intercept transaction commit
|
||||
* or rollback, respectively.
|
||||
* <p>Interactions with the underlying transactional resource will not be
|
||||
* committed in this phase. See
|
||||
* {@link TransactionSynchronization#afterCompletion(int)} for details.
|
||||
* @see TransactionSynchronization#afterCompletion(int)
|
||||
*/
|
||||
AFTER_COMPLETION
|
||||
|
||||
@@ -33,9 +33,10 @@ import org.springframework.lang.Nullable;
|
||||
* transaction completion.
|
||||
*
|
||||
* <p><b>NOTE: Transactional event listeners only work with thread-bound transactions
|
||||
* managed by {@link org.springframework.transaction.PlatformTransactionManager}.</b>
|
||||
* A reactive transaction managed by {@link org.springframework.transaction.ReactiveTransactionManager}
|
||||
* uses the Reactor context instead of thread-local attributes, so from the perspective of
|
||||
* managed by a {@link org.springframework.transaction.PlatformTransactionManager
|
||||
* PlatformTransactionManager}.</b> A reactive transaction managed by a
|
||||
* {@link org.springframework.transaction.ReactiveTransactionManager ReactiveTransactionManager}
|
||||
* uses the Reactor context instead of thread-local variables, so from the perspective of
|
||||
* an event listener, there is no compatible active transaction that it can participate in.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
|
||||
@@ -27,22 +27,34 @@ import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
/**
|
||||
* An {@link EventListener} that is invoked according to a {@link TransactionPhase}.
|
||||
* This is an an annotation-based equivalent of {@link TransactionalApplicationListener}.
|
||||
* This is an annotation-based equivalent of {@link TransactionalApplicationListener}.
|
||||
*
|
||||
* <p>If the event is not published within an active transaction, the event is discarded
|
||||
* unless the {@link #fallbackExecution} flag is explicitly set. If a transaction is
|
||||
* running, the event is processed according to its {@code TransactionPhase}.
|
||||
* running, the event is handled according to its {@code TransactionPhase}.
|
||||
*
|
||||
* <p>Adding {@link org.springframework.core.annotation.Order @Order} to your annotated
|
||||
* method allows you to prioritize that listener amongst other listeners running before
|
||||
* or after transaction completion.
|
||||
*
|
||||
* <p><b>NOTE: Transactional event listeners only work with thread-bound transactions
|
||||
* managed by {@link org.springframework.transaction.PlatformTransactionManager}.</b>
|
||||
* A reactive transaction managed by {@link org.springframework.transaction.ReactiveTransactionManager}
|
||||
* uses the Reactor context instead of thread-local attributes, so from the perspective of
|
||||
* managed by a {@link org.springframework.transaction.PlatformTransactionManager
|
||||
* PlatformTransactionManager}.</b> A reactive transaction managed by a
|
||||
* {@link org.springframework.transaction.ReactiveTransactionManager ReactiveTransactionManager}
|
||||
* uses the Reactor context instead of thread-local variables, so from the perspective of
|
||||
* an event listener, there is no compatible active transaction that it can participate in.
|
||||
*
|
||||
* <p><strong>WARNING:</strong> if the {@code TransactionPhase} is set to
|
||||
* {@link TransactionPhase#AFTER_COMMIT AFTER_COMMIT} (the default),
|
||||
* {@link TransactionPhase#AFTER_ROLLBACK AFTER_ROLLBACK}, or
|
||||
* {@link TransactionPhase#AFTER_COMPLETION AFTER_COMPLETION}, the transaction will
|
||||
* have been committed or rolled back already, but the transactional resources might
|
||||
* still be active and accessible. As a consequence, any data access code triggered
|
||||
* at this point will still "participate" in the original transaction, but changes
|
||||
* will not be committed to the transactional resource. See
|
||||
* {@link org.springframework.transaction.support.TransactionSynchronization#afterCompletion(int)
|
||||
* TransactionSynchronization.afterCompletion(int)} for details.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Sam Brannen
|
||||
* @author Oliver Drotbohm
|
||||
@@ -65,7 +77,7 @@ public @interface TransactionalEventListener {
|
||||
TransactionPhase phase() default TransactionPhase.AFTER_COMMIT;
|
||||
|
||||
/**
|
||||
* Whether the event should be processed if no transaction is running.
|
||||
* Whether the event should be handled if no transaction is running.
|
||||
*/
|
||||
boolean fallbackExecution() default false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user