This is related to SpringBatch but the issue might be Spring Core so let me know if I need to re-post it somewhere else. I am facing seems to be related to JDBC and Spring Core so posting it here.
I ahve a job that is using a CompositeItemWriter which has a delegate writer which uses JDBC Template to persist data in the Oracle db. I have implemented a StepListener which has overridden the callback method OnWriteError ((of ItemWriterListener)) and in this method deletes any rows inserted by the writer before that error/exception occurred. I am using same dataSource for all activities. What happening is that the implementation inside the OnWriterError tries to delete the data inserted by the writer but as it is running under the same transaction as the writer, the deletion is rolled back. I have tried to change this behaviour by configuring the transaction attributed and proxying my Dao class. Configurations are as fellows:
The job:
The writers:Code:<batch:job id="CounterFileProcessJob" job-repository="jobRepository" incrementer="jobParamatersIncrementer"> <batch:step id="CounterFileProcessJobStep" > <batch:tasklet transaction-manager="jobRepository-transactionManager"> <batch:chunk reader="tpiAccumulatorInboundReader" processor="tpiAccumulatorInboundProcessor" writer="tpiAccumumlatorCompositeWriter" commit-interval="1"> <batch:streams> <batch:stream ref="tpiAccumulatorEX07InboundWriter" /> <batch:stream ref="consumptionJDBCWriter" /> </batch:streams> </batch:chunk> <batch:listeners> <batch:listener ref="coreStepListener" /> <batch:listener ref="consumptionJDBCWriter" /> </batch:listeners> </batch:tasklet> </batch:step> </batch:job>
Code:<bean id="tpiAccumumlatorCompositeWriter" scope="step" class="org.hphc.batch.tpi.accumulator.inbound.OHBSCounterCompositeWriter"> <property name="delegates"> <list> <ref bean="tpiAccumulatorEX07InboundWriter" /> <ref bean="consumptionJDBCWriter" /> </list> </property> </bean> <bean id="consumptionJDBCWriter" scope="step" class="org.hphc.batch.tpi.accumulator.inbound.ConsumptionJDBCWriter"> <property name="daoFactory" ref="daoFactory" /> </bean>
The Listener:
The transaction proxy setting (the clean* method is the one in need of a new transaction):Code:<bean id="coreStepListener" scope="step" class="org.hphc.batch.tpi.accumulator.inbound.listener.CoreStepListener"> <property name="fileName" value="#{jobParameters['outputFileName']}" /> <property name="fileFormatSpecificationFactory" ref="fileFormatSpecificationFactory" /> <property name="lineAggregator" ref="ex07LineAggregator" /> <property name="cleanUpDao" ref="pcleanUpDao" /> </bean>
Code:<bean id="daoFactory" class="org.hphc.batch.tpi.accumulator.inbound.dao.impl.DAOFactoryImpl"> <property name="migrationAccumulationDao" ref="pMigrationAccumulationDao" /> </bean> <bean id="pMigrationAccumulationDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="transactionManager" /> <property name="target" ref="migrationAccumulationDao" /> <property name="proxyTargetClass" value="true" /> <property name="transactionAttributes"> <props> <prop key="clean*">PROPAGATION_REQUIRES_NEW</prop> <prop key="save*">PROPAGATION_REQUIRED, -Exception</prop> </props> </property> </bean>
OnWriterError method (this deletion isn't committed as the earlier/parent transaction is marked for rolled back even if this method is REQUIRES_NEW):
Code:public void onWriteError(Exception exception, List<? extends List<CounterRecord>> items) { pMigrationAccumulationDao.cleanMigrationAccumulationsOnError(batchId); }
Even if I set PROPAGATION_REQUIRES_NEW attribute for above 'clean' method, it does not work and my deletion query is rolled back too.
My DAO (pMigrationAccumulationDao) is extending JDBCDaoSupport. Please advise that what am I doing wrong? Thanks a lot.


Reply With Quote