Spring: Accessing JPA repository from TaskExecutor thread

I'm using JPA and Hibernate for persistence, with some autoconfiguration help from Spring Boot. I'm running a JUnit test which saves some record in the JPA Repository. Then it instantiates a new Spring-managed-thread, and it's run by ThreadPoolTaskExecutor. That thread will try to get that previously added record with no success. Here is the relevant code of the test and the runnable thread: <code> public class RtmpSpyingTests extends AbstractTransactionalJUnit4SpringContextTests { @Autowired ThreadPoolTaskExecutor rtmpSpyingTaskExecutor; @Autowired ApplicationContext ctx; @Autowired RtmpSourceRepository rtmpRep; @Test public void test() { RtmpSource rtmpSourceSample = new RtmpSource("test"); rtmpRep.save(rtmpSourceSample); rtmpRep.flush(); List<RtmpSource> rtmpSourceList = rtmpRep.findAll(); // Here I get a list containing rtmpSourceSample RtmpSpyingTask rtmpSpyingTask = ctx.getBean(RtmpSpyingTask.class, "arg1","arg2"); rtmpSpyingTaskExecutor.execute(rtmpSpyingTask); } } public class RtmpSpyingTask implements Runnable { @Autowired RtmpSourceRepository rtmpRep; String nameIdCh; String rtmpUrl; public RtmpSpyingTask(String nameIdCh, String rtmpUrl) { this.nameIdCh = nameIdCh; this.rtmpUrl = rtmpUrl; } public void run() { // Here I should get a list containing rtmpSourceSample, but instead of that // I get an empty list List<RtmpSource> rtmpSource = rtmpRep.findAll(); } } </code> So, after I have inserted the rtmpSourceSample object, I can check it's been inserted from the test method, it is indeed on the rtmpSourceList list. However, when I do the same from the thread, what I get is an empty list. Here is the JPA/Hibernate configuration in my spring-context.xml configuration file: <code> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="org.h2.Driver" /> <property name="url" value="jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;MVCC=true" /> <property name="username" value="user" /> <property name="password" value="user" /> </bean> <!-- Define the JPA transaction manager --> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <constructor-arg ref="entityManagerFactory" /> </bean> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="jpaVendorAdapter" ref="vendorAdaptor" /> <property name="packagesToScan" value="guiatv.persistence.domain" /> </bean> <bean id="abstractVendorAdaptor" abstract="true"> <property name="generateDdl" value="true" /> <property name="database" value="H2" /> <property name="showSql" value="false" /> </bean> <bean id="entityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <bean id="vendorAdaptor" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" parent="abstractVendorAdaptor"> </bean> <context:annotation-config /> <tx:annotation-driven /> <context:component-scan base-package="guiatv.persistence" /> </code> Note that the persistence-unit.xml is not needed since I'm using Spring Boot. And finally this is the xml configuration of the taskexecutor bean and the runnable thread: <code> <bean id="rtmpSpyingTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <property name="corePoolSize" value="5" /> <property name="maxPoolSize" value="5" /> <property name="queueCapacity" value="5" /> </bean> <bean id="rtmpSpyingTask" class="guiatv.realtime.rtmpspying.RtmpSpyingTask" scope="prototype"> <constructor-arg ref="rtmpSpyingTaskExecutor" /> </bean> </code> I've been looking for topics about this problematic Spring's persistence and threading combination. One of the solutions I've found so far is to create some @Service annotated class with a @Transactional method, which I am supposed to call from my run() method. It does not work for me. Some other solutions involve the use of the EntityManager or some other Hibernate dependent bean, instead of querying the JPA Repository directly. Doesn't work too. So, any solution that could fit my needs? Thank you!
1 answer

use requires new for synchronous code that asynchronous code needs to access

the thread does not see the record because the test runs inside a transaction that is not committed yet. since the transaction is bound to the executing thread the task that is forked does not use the same transaction. in order for this to work the insert must run in a method that is annotated with @Transactional(propagation = REQUIRES_NEW). please note that transactional rollback will not work then though