Recently, we have upgraded Spring Boot version from 2.2.2.RELEASE to 2.7.18. Hence, the Spring Batch version is upgraded from 4.2.x to 4.3.10.
What before worked is not working after this upgradation in Spring Batch 4.3.10. Hence, I downgraded the batch to 4.2.5.RELEASE to confirm. It's working without any change in my Spring Batch read and write method.
Exception that i'm facing in Spring batch 4.3.10
.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is java.lang.IllegalStateException: Already value [.springframework.jdbc.datasource.ConnectionHolder@69d7cd50] for key [net.ttddyy.dsproxy.support.ProxyDataSource@12330130] bound to thread
at .springframework.orm.hibernate5.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:600)
at .springframework.transaction.support.AbstractPlatformTransactionManager.startTransaction(AbstractPlatformTransactionManager.java:400)
at .springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at .springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:595)
at .springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:382)
at .springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at .springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at .springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
at .springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:707)
at com.wesea.frameworkdesign.base.model.dao.CompanyDAO$$EnhancerBySpringCGLIB$$e793a2c3.findCompanyByName(<generated>)
at com.wesea.appointmentdesign.service.batch.BatchService.createTruckCompany(BatchService.java:97)
at com.wesea.appointmentdesign.service.batch.TruckingCompanyDetailsWriter.write(TruckingCompanyDetailsWriter.java:103)
at .springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:193)
at .springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:159)
at .springframework.batch.core.step.item.SimpleChunkProcessor.write(SimpleChunkProcessor.java:294)
at .springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:217)
at .springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:77)
at .springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407)
at .springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCal
What I found in the version 4.3.10 is, HibernateTransactionManager's sessionHolder seems to be null. At the same time, if i check the same in 4.2.5 version, it's not null and TransactionStaus is ACTIVE
HibernateTransactionManager in 4.3.10
HibernateTransactionManager in 4.2.5
So it return's existing Trancation as below. Could you please help me on this ? I red the document enter link description here for 4.3.10 and do needful. but no luck. Thanks
Returning Existing Transaction
enter image description here
I tried this in Stack overflow and the Spring batch docs spring batch docs for the specfic version. But no luck
Minimal, Reproducible Example
@Override
public List<String> read() throws UnexpectedInputException,
ParseException, NonTransientResourceException, IOException {
List<String> list = new ArrayList<>();
StringReader reader = new StringReader(inputData);
BufferedReader bufferedReader = new BufferedReader(reader);
String truckRecord = bufferedReader.readLine();
while (truckRecord != null) {
list.add(truckRecord);
truckRecord = bufferedReader.readLine();
}
return list;
}
public void write(List<? extends List<String>> list) throws InvalidFormatException, IOException {
CompanyEntity companyEntity= companyDAO.findCompanyByName("COMPANY_NAME");
List<String> recordList = list.get(0);
List<TruckingCompanyEntity> truckingCompanyEntities = new ArrayList<>();
for (String companyDetails : recordList) {
truckingCompanyEntities.add(readCompanyDetails(companyDetails));
}
//here, mapping company to the TruckingCompany and saving TruckingCompany
}
My DataSource is created through ProxyDataSourceBuilder
and with HikariDataSource
(with afterPropertiesSet()
).
SessionFactory
using above DataSource
(with afterPropertiesSet()
)
My TransactionManager is HibernateTransactionManager
using above sessionFactory
Important note is: my Reader and Writer implementation class is not @Transactional
. But my companyDAO is @Repository
and @Transactional