Skip to content

@TransactionalEventListener does not work with SimpleApplicationEventMulticaster.setTaskExecutor #30244

New issue

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

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

Already on GitHub? # to your account

Closed
Basnucaev0 opened this issue Mar 30, 2023 · 1 comment
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) in: data Issues in data modules (jdbc, orm, oxm, tx) type: enhancement A general enhancement
Milestone

Comments

@Basnucaev0
Copy link

If the ApplicationEventMulticaster bean appears in the context, the @TransactionalEventListener annotation is useless, it will not work a priori and is not mentioned anywhere.

At the stage of this method, there is still a transaction in the publish event call chain, SimpleApplicationEventMulticaster.multicastEvent:

        @Override
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		Executor executor = getTaskExecutor();
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				invokeListener(listener, event);
			}
		}
	}

If we have an ApplicationEventMulticaster bean, then the first if will be executed and invokeListener will be executed deferred in a separate thread WHERE OUR TRANSACTION WILL NOT BE ALREADY.

Here's what's happening in invokeListener -> doInvokeListener -> TransactionalApplicationListenerMethodAdapter.onApplicationEvent():

	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		if (TransactionSynchronizationManager.isSynchronizationActive() &&
				TransactionSynchronizationManager.isActualTransactionActive()) {
			TransactionSynchronizationManager.registerSynchronization(
					new TransactionalApplicationListenerSynchronization<>(event, this, this.callbacks));
		}
		else if (this.annotation.fallbackExecution()) {
			if (this.annotation.phase() == TransactionPhase.AFTER_ROLLBACK && logger.isWarnEnabled()) {
				logger.warn("Processing " + event + " as a fallback execution on AFTER_ROLLBACK phase");
			}
			processEvent(event);
		}
		else {
			// No transactional event execution at all
			if (logger.isDebugEnabled()) {
				logger.debug("No transaction is active - skipping " + event);
			}
		}
	}

When this code is executed asynchronously in a separate thread (executor), the transaction no longer exists.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 30, 2023
@rstoyanchev rstoyanchev added the in: data Issues in data modules (jdbc, orm, oxm, tx) label Apr 11, 2023
@jhoeller jhoeller changed the title @TransactionalEventListener does not work when the context have bean of ApplicationEventMulticaster @TransactionalEventListener does not work with SimpleApplicationEventMulticaster.setTaskExecutor Aug 1, 2023
@jhoeller jhoeller self-assigned this Aug 1, 2023
@jhoeller jhoeller added type: enhancement A general enhancement in: core Issues in core modules (aop, beans, core, context, expression) and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Aug 1, 2023
@jhoeller jhoeller added this to the 6.1.0-M4 milestone Aug 1, 2023
@jhoeller
Copy link
Contributor

jhoeller commented Aug 1, 2023

Related issue: #25129

We can mark TransactionalApplicationListener with an indicator that it needs to always execute in the caller's thread and react to that in SimpleApplicationEventMulticaster, bypassing a potential custom executor for such a listener there.

@sbrannen sbrannen changed the title @TransactionalEventListener does not work with SimpleApplicationEventMulticaster.setTaskExecutor @TransactionalEventListener does not work with SimpleApplicationEventMulticaster.setTaskExecutor Aug 1, 2023
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) 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