spring-boothibernatespring-data-jpaspring-async

Async Transactional Saves do not work in Spring after upgrade


We upgraded Spring Boot from 1.5.8 to 2.6.2. It has introduced a problem that has us perplexed: Transactional saves are not processing from inside spawned threads.

We use JPA managed entities on a Mysql database and make calls down to the CrudRepository to save them.

Transactions inside the main thread work fine. However, when called from an asynchronous operation things go awry:

We have tried different things to get this to work. For example, we used the transactionTemplate to have some specific control here, but that has not changed the behavior.

We were originally creating this async process by using the ApplicationEventPublisher to create an event. We also tried using completablefuture and other constructs with the same result as well as annotating the method with @Async and calling it directly.


Solution

  • The issue was that, with the upgrade to Spring Boot 2.6, Spring Batch implements a new Transaction Manager.

    What we didn't realize is that this transaction manager was being autowired into our other services and did not work in this threaded context. You do not want to share a Batch processing Tx Manager with your API/misc services. Declaring a specific Transaction Manager there to keep them separate solved the issue.

    Here is an example marking a PlatformTransactionManager with the Primary annotation to test its usage explicitly.

    @Primary
    @Bean
    public PlatformTransactionManager platformTransactionManager(DataSource dataSource) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory(dataSource).getObject());
        return transactionManager;
    }