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

It seems like there is a connection leak issue with the entityManager. #3157

Closed
bperhaps opened this issue Sep 12, 2023 · 1 comment
Closed
Labels
status: waiting-for-triage An issue we've not yet triaged

Comments

@bperhaps
Copy link

bperhaps commented Sep 12, 2023

It seems like there might be a Connection Leak issue when using the NOT_SUPPORTED propagation attribute or creating a transactionless state in Spring Batch and then calling a non-transactional Repository.

The commonality is that, in both NOT_SUPPORTED and BATCH codes, TransactionSynchronizationManager has activeTransaction set to false and the ResourceMap is empty, but TransactionSynchronizationManager.isSynchronizationActive() returns true.

Looking at the example below might make it easier.

@Service
@RequiredArgsConstructor
public class TestService {

    private final TestService2  testService2;
    @Transactional
    public void test() {
        testService2.test();
    }
}

@Service
@RequiredArgsConstructor
public class TestService2 {

    private final TestRepository TestRepository;

    @Transactional(propagation = NOT_SUPPORTED)
    public void test() {
        var e = TestRepository.findByIdNoTx(1L);
    }
}

In the scenario described above, after executing the repository in TestService2::test, the connection remains in the TransactionSynchronizationManager's ResourceMap without being properly removed.

Typically, users might believe that since there is no transaction, the connection will be immediately released. However, it seems that in this case, that assumption does not hold true.

Below is an example of a Spring Batch scenario:

    @Bean
    public Step step1() {
        DefaultTransactionAttribute transactionAttribute = new DefaultTransactionAttribute();
        transactionAttribute.setPropagationBehavior(Propagation.NEVER.value());

        return stepBuilderFactory.get("step1").tasklet((contribution, chunkContext) -> {
                var e = testRepository.findByIdNoTx(1L);
                return RepeatStatus.FINISHED;
            })
            .transactionAttribute(transactionAttribute)
            .build();
    }

Even in cases like the one described, it seems that after the execution of testRepository.findByIdNoTx(), the transaction manager retains the resource in the resource map, leading to the connection not being released as expected.

The problem described above can cause an exception due to db wiat_timeout when the user creates logic that takes a long time between two repository requests (expecting no connection because there is no transaction).

The cause of the problem seems to be the entityManager creation availability branch in EntityManagerFactoryUtils.

		else if (!TransactionSynchronizationManager.isSynchronizationActive()) {
			// Indicate that we can't obtain a transactional EntityManager.
			return null;
		}

Line 249 in EntityManagerFactoryUtils is currently using only isSynchronizationActive() for validation.

After creating a typical API application, if you execute the code like the one in the example above when there is no transaction, the TransactionSynchronizationManager.isSynchronizationActive() will be marked as false, returning null, and not maintaining the connection.
I believe this approach is correct.

I'm curious about your thoughts on adding the following validation logic here:

else if (!TransactionSynchronizationManager.isActualTransactionActive() || !TransactionSynchronizationManager.isSynchronizationActive()) {
			// Indicate that we can't obtain a transactional EntityManager.
			return null;
		}

Thank you!

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Sep 12, 2023
@bperhaps
Copy link
Author

The repository is selected incorrectly and closed.
spring-projects/spring-framework#31209

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: waiting-for-triage An issue we've not yet triaged
Projects
None yet
Development

No branches or pull requests

2 participants