diff --git a/spring-context/src/main/java/org/springframework/context/event/EventListener.java b/spring-context/src/main/java/org/springframework/context/event/EventListener.java index 0f3cf4017d..2357f6dc6c 100644 --- a/spring-context/src/main/java/org/springframework/context/event/EventListener.java +++ b/spring-context/src/main/java/org/springframework/context/event/EventListener.java @@ -84,6 +84,7 @@ import org.springframework.core.annotation.AliasFor; * @author Sam Brannen * @since 4.2 * @see EventListenerMethodProcessor + * @see org.springframework.transaction.event.TransactionalEventListener */ @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) diff --git a/spring-tx/src/main/java/org/springframework/transaction/event/TransactionPhase.java b/spring-tx/src/main/java/org/springframework/transaction/event/TransactionPhase.java index 31680a6f95..03f530cdb1 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/event/TransactionPhase.java +++ b/spring-tx/src/main/java/org/springframework/transaction/event/TransactionPhase.java @@ -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. - *
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. + *
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()}). + *
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. - *
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. + *
Note: This is a specialization of {@link #AFTER_COMPLETION} and therefore + * executes in the same sequence of events as {@code AFTER_COMPLETION}. + *
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. *
For more fine-grained events, use {@link #AFTER_COMMIT} or * {@link #AFTER_ROLLBACK} to intercept transaction commit * or rollback, respectively. + *
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 diff --git a/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListener.java b/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListener.java index b90ed812ea..e829fe3042 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListener.java +++ b/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalApplicationListener.java @@ -33,9 +33,10 @@ import org.springframework.lang.Nullable; * transaction completion. * *
NOTE: Transactional event listeners only work with thread-bound transactions - * managed by {@link org.springframework.transaction.PlatformTransactionManager}. - * 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}. 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 diff --git a/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalEventListener.java b/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalEventListener.java index 20968245c9..f70022e7cd 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalEventListener.java +++ b/spring-tx/src/main/java/org/springframework/transaction/event/TransactionalEventListener.java @@ -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}. * *
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}. * *
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. * *
NOTE: Transactional event listeners only work with thread-bound transactions - * managed by {@link org.springframework.transaction.PlatformTransactionManager}. - * 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}. 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. * + *
WARNING: 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;