Skip to content

Method invocation in same class when both methods are @Transactional, but method 2 never executes #27534

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

Closed
hxlqjz opened this issue Oct 8, 2021 · 3 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) in: data Issues in data modules (jdbc, orm, oxm, tx) status: invalid An issue that we don't feel is valid

Comments

@hxlqjz
Copy link

hxlqjz commented Oct 8, 2021

I want to use Propagation.REQUIRES_NEW to start a new transaction, but test2 never be executed and process has been hang up. Is there any thing wrong in my example?

here is my code,

    @Override 
    @Transactional(rollbackFor = Exception.class)
    public void test() {
        ((TestServiceImpl) AopContext.currentProxy()).test2();
        log.info("2222222222222222222");

    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void test2() {
        log.info("11111111");
    }
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Oct 8, 2021
@sbrannen sbrannen added in: core Issues in core modules (aop, beans, core, context, expression) in: data Issues in data modules (jdbc, orm, oxm, tx) labels Oct 8, 2021
@sbrannen sbrannen self-assigned this Oct 8, 2021
@sbrannen sbrannen added status: invalid An issue that we don't feel is valid and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Oct 8, 2021
@sbrannen
Copy link
Member

sbrannen commented Oct 8, 2021

Use of AopContext.currentProxy() within application code is highly discouraged. In addition, it will throw an IllegalStateException if you don't configure the ProxyFactory to expose the proxy. I assume that's the case in your scenario and that the exception is causing issues.

In any case, a better way to achieve your goal is to make use of self injection or self reference by injecting a lazy proxy to yourself (which ends up accessing the transactional proxy).

For example, the test class below prints:

test 1 :: example.TestServiceImpl.test1
test 2 :: example.TestServiceImpl.test2

This verifies that a new transaction was started for the invocation of self.test2().

You can also turn on DEBUG logging for org.springframework.jdbc.datasource to see more details.

package example;

// imports

@SpringJUnitConfig
class SelfReferenceTests {

	@Test
	void test(@Autowired TestService testService) {
		testService.test1();
	}

	@Configuration
	@EnableTransactionManagement
	@Import(TestServiceImpl.class)
	static class Config {

		@Bean
		TransactionManager transactionManager(DataSource dataSource) {
			return new DataSourceTransactionManager(dataSource);
		}

		@Bean
		DataSource dataSource() {
			return new EmbeddedDatabaseBuilder().generateUniqueName(true).build();
		}
	}
}

interface TestService {
	void test1();
	void test2();
}

class TestServiceImpl implements TestService {

	private final TestService self;

	TestServiceImpl(@Lazy TestService self) {
		this.self = self;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void test1() {
		System.err.println("test 1 :: " + TransactionSynchronizationManager.getCurrentTransactionName());
		self.test2();
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void test2() {
		System.err.println("test 2 :: " + TransactionSynchronizationManager.getCurrentTransactionName());
	}
}

In light of that, I am closing this issue.

@sbrannen sbrannen closed this as completed Oct 8, 2021
@sbrannen sbrannen changed the title function call in same class and both method have @Transactional, but method2 never execute Method invocation in same class when both methods are @Transactional, but method 2 never executes Oct 8, 2021
@b19g3r
Copy link

b19g3r commented Jan 12, 2024

Use of AopContext.currentProxy() within application code is highly discouraged.

@sbrannen
Could you explain why? Thanks. And is it useable for now?
Thanks again.

@sbrannen
Copy link
Member

@b19g3r, the answer to your question is in the class-level Javadoc for AopContext:

The functionality in this class might be used by a target object that needed access to resources on the invocation. However, this approach should not be used when there is a reasonable alternative, as it makes application code dependent on usage under AOP and the Spring AOP framework in particular.

In the future, please ensure that you have read all related documentation before asking questions, or alternatively ask on Stack Overflow.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) in: data Issues in data modules (jdbc, orm, oxm, tx) status: invalid An issue that we don't feel is valid
Projects
None yet
Development

No branches or pull requests

4 participants