Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect invalid transaction configuration for transactional event listeners #30679

Closed
odrotbohm opened this issue Jun 15, 2023 · 3 comments
Closed
Assignees
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) type: enhancement A general enhancement
Milestone

Comments

@odrotbohm
Copy link
Member

Problem

It's common practice to use a simple (no custom attributes) @Transactional on methods to execute them wrapped in a transaction. Unfortunately, for methods declared as @TransactionalEventListener, this doesn't work as expected:

@Component
class SomeListener {

  @Transactional
  @TransactionalEventListener
  void on(SomeEvent event) { /* … */ }
}

Those methods are invoked in the transaction cleanup phase of an original, other transaction. This means that this particular, other transaction is still running, although in an undefined state. With a simple @Transactional declared on those methods, the code would be executed in an undefined transactional state. An obvious solution to this problem is to declare a Propagation of REQUIRES_NEW on the listener method, so that it will run in a new transaction:

@Component
class SomeListener {

  @Transactional(propagation = Propagation.REQUIRES_NEW)
  @TransactionalEventListener
  void on(SomeEvent event) { /* … */ }
}

Proposed solution

It would be nice if the erroneous arrangement shown above would be rejected, ideally at bootstrap (potentially even AOT?) time. We have to consider that a plain @Transactional is still valid in the case of the method declared to be invoked asynchronously (using @Async). In other words, a declaration like this is still valid, as the asynchronous invocation triggers the execution on a separate thread and thus a clean slate regarding transactions.

@Component
class SomeListener {

  @Async
  @Transactional
  @TransactionalEventListener
  void on(SomeEvent event) { /* … */ }
}
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jun 15, 2023
@jhoeller jhoeller self-assigned this Jun 15, 2023
@jhoeller jhoeller added in: data Issues in data modules (jdbc, orm, oxm, tx) type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jun 15, 2023
@jhoeller jhoeller added this to the 6.1.0-M2 milestone Jun 15, 2023
@quaff
Copy link
Contributor

quaff commented Jun 19, 2023

After 842569c

@Component
class SomeListener {

  @Transactional(propagation = Propagation.REQUIRES_NEW)
  @TransactionalEventListener
  void on(SomeEvent event) { /* … */ }
}

will not be valid, is it intentional? @jhoeller

@jhoeller
Copy link
Contributor

Good point, the check seems too restrictive now. I'll revise it to be lenient towards REQUIRES_NEW.

mdeinum pushed a commit to mdeinum/spring-framework that referenced this issue Jun 29, 2023
mdeinum pushed a commit to mdeinum/spring-framework that referenced this issue Jun 29, 2023
jhoeller added a commit that referenced this issue Jul 12, 2023
AbstractTransactionManagementConfiguration.transactionalEventListenerFactory() creating a RestrictedTransactionalEventListenerFactory now.

See gh-30679
@jhoeller
Copy link
Contributor

jhoeller commented Oct 11, 2023

I'm inclined to enforce REQUIRES_NEW here since that is semantically correct for such a listener in general. Even with @Async execution, it would be self-descriptive to always declare REQUIRES_NEW there. Also, our check in the transaction package cannot actually enforce actual async execution, it can only check for the presence of the common @Async annotation without knowing whether the corresponding runtime setup is active.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

4 participants