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");
    }

Comment From: sbrannen

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.

Comment From: b19g3r

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

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

Comment From: sbrannen

@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