Skip to content

Commit d022fcf

Browse files
committed
Explicit note on TransactionalEventListener versus reactive transactions
Closes gh-25805
1 parent e028ef8 commit d022fcf

File tree

2 files changed

+31
-17
lines changed

2 files changed

+31
-17
lines changed

spring-tx/src/main/java/org/springframework/transaction/event/TransactionalEventListener.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -36,6 +36,12 @@
3636
* method allows you to prioritize that listener amongst other listeners running before
3737
* or after transaction completion.
3838
*
39+
* <p><b>NOTE: Transactional event listeners only work with thread-bound transactions
40+
* managed by {@link org.springframework.transaction.PlatformTransactionManager}.</b>
41+
* A reactive transaction managed by {@link org.springframework.transaction.ReactiveTransactionManager}
42+
* uses the Reactor context instead of thread-local attributes, so from the perspective of
43+
* an event listener, there is no compatible active transaction that it can participate in.
44+
*
3945
* @author Stephane Nicoll
4046
* @author Sam Brannen
4147
* @since 4.2

src/docs/asciidoc/data-access.adoc

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2619,8 +2619,8 @@ number of transactional operations. For example, if you have a web application t
26192619
requires transactions only for certain update operations, you may not want to set up
26202620
transactional proxies by using Spring or any other technology. In this case, using the
26212621
`TransactionTemplate` may be a good approach. Being able to set the transaction name
2622-
explicitly is also something that can be done only by using the programmatic approach to
2623-
transaction management.
2622+
explicitly is also something that can be done only by using the programmatic approach
2623+
to transaction management.
26242624

26252625
On the other hand, if your application has numerous transactional operations,
26262626
declarative transaction management is usually worthwhile. It keeps transaction
@@ -2633,14 +2633,14 @@ management is greatly reduced.
26332633
[[transaction-event]]
26342634
=== Transaction-bound Events
26352635

2636-
As of Spring 4.2, the listener of an event can be bound to a phase of the transaction. The
2637-
typical example is to handle the event when the transaction has completed successfully. Doing so
2638-
lets events be used with more flexibility when the outcome of the current transaction
2639-
actually matters to the listener.
2636+
As of Spring 4.2, the listener of an event can be bound to a phase of the transaction.
2637+
The typical example is to handle the event when the transaction has completed successfully.
2638+
Doing so lets events be used with more flexibility when the outcome of the current
2639+
transaction actually matters to the listener.
26402640

2641-
You can register a regular event listener by using the `@EventListener` annotation. If you need
2642-
to bind it to the transaction, use `@TransactionalEventListener`. When you do so, the listener
2643-
is bound to the commit phase of the transaction by default.
2641+
You can register a regular event listener by using the `@EventListener` annotation.
2642+
If you need to bind it to the transaction, use `@TransactionalEventListener`.
2643+
When you do so, the listener is bound to the commit phase of the transaction by default.
26442644

26452645
The next example shows this concept. Assume that a component publishes an order-created
26462646
event and that we want to define a listener that should only handle that event once the
@@ -2672,14 +2672,22 @@ example sets up such an event listener:
26722672
}
26732673
----
26742674

2675-
The `@TransactionalEventListener` annotation exposes a `phase` attribute that lets you customize
2676-
the phase of the transaction to which the listener should be bound. The valid phases are `BEFORE_COMMIT`,
2677-
`AFTER_COMMIT` (default), `AFTER_ROLLBACK`, and `AFTER_COMPLETION` that aggregates the transaction
2678-
completion (be it a commit or a rollback).
2675+
The `@TransactionalEventListener` annotation exposes a `phase` attribute that lets you
2676+
customize the phase of the transaction to which the listener should be bound.
2677+
The valid phases are `BEFORE_COMMIT`, `AFTER_COMMIT` (default), `AFTER_ROLLBACK`, as well as
2678+
`AFTER_COMPLETION` which aggregates the transaction completion (be it a commit or a rollback).
2679+
2680+
If no transaction is running, the listener is not invoked at all, since we cannot honor the
2681+
required semantics. You can, however, override that behavior by setting the `fallbackExecution`
2682+
attribute of the annotation to `true`.
26792683

2680-
If no transaction is running, the listener is not invoked at all, since we cannot honor the required
2681-
semantics. You can, however, override that behavior by setting the `fallbackExecution` attribute
2682-
of the annotation to `true`.
2684+
[NOTE]
2685+
====
2686+
`@TransactionalEventListener` only works with thread-bound transactions managed by
2687+
`PlatformTransactionManager`. A reactive transaction managed by `ReactiveTransactionManager`
2688+
uses the Reactor context instead of thread-local attributes, so from the perspective of
2689+
an event listener, there is no compatible active transaction that it can participate in.
2690+
====
26832691

26842692

26852693

0 commit comments

Comments
 (0)