0
votes

I have a custom Item reader which reads data another reader which is a JdbcCursorItemReader (Which reads data from the Request table in the database), builds a list of specific size and returns a list of items.

The request table has an id, type and a status.

I want to update the status of the id's that have been read by the reader to something like PROCESSING so my application can display that the request ids are being processing in the batch. Also while processing the items if there is any business exception, I want to update the table for the ids with certain status.

I wanted the status updating part to be in a separate transaction so that if an item is read and is being processed the status for those requests says PROCESSING rather than REQUESTED.

I am using @Transactional(propagation=Propagation.REQUIRES_NE W) on the method which updates the status of the request.

I am using separate data sources and transaction managers for spring batch tables and my application specific tables.

I am using JDBC template to update the status.

I am using javax.sql.DataSource for my application data source, JpaTransactionManager for my application transaction manager and HibernateJpaVendorAdapter.

The database is Oracle.

When I turn the debug log on, I see that it suspends the main transactions, a new transaction is being used when update status is being called from the reader, it is committed and then resumes the suspended transaction. But I dont see the change on the database. The transaction log says committed but I dont see the changes in the database. Once the batch completes then I see the changes to the request table in the database. Am I missing something?

Here is the log: 15:40:26 [main] DEBUG o.s.t.a.AnnotationTransactionAttributeSource - Adding transactional method 'updateStatus' with attribute: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT; '' 15:40:48 [main] DEBUG o.s.o.j.JpaTransactionManager - Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 15:40:48 [main] DEBUG o.s.o.j.JpaTransactionManager - Opened new EntityManager [org.hibernate.ejb.EntityManagerImpl@36dd518b] for JPA transaction 15:40:48 [main] DEBUG o.h.e.t.s.AbstractTransactionImpl - begin 15:40:48 [main] DEBUG o.h.e.j.i.LogicalConnectionImpl - Obtaining JDBC connection 15:40:48 [main] DEBUG o.h.e.j.i.LogicalConnectionImpl - Obtained JDBC connection 15:40:48 [main] DEBUG o.h.e.t.i.j.JdbcTransaction - initial autocommit status: true 15:40:48 [main] DEBUG o.h.e.t.i.j.JdbcTransaction - disabling autocommit 15:40:48 [main] DEBUG o.s.o.j.JpaTransactionManager - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@3a7b058e] 15:40:48 [main] INFO c.c.c.f.c.a.b.RequestReader - Reading... 15:40:48 [main] INFO c.c.c.f.c.a.b.SecuritiesReader - End of Input Data from request id ItemReader 15:40:48 [main] DEBUG o.s.o.j.JpaTransactionManager - Creating new transaction with name [*.updateStatus]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT; '' 15:40:48 [main] DEBUG o.s.o.j.JpaTransactionManager - Opened new EntityManager [org.hibernate.ejb.EntityManagerImpl@628b6e47] for JPA transaction 15:40:48 [main] DEBUG o.h.e.t.s.AbstractTransactionImpl - begin 15:40:48 [main] DEBUG o.h.e.j.i.LogicalConnectionImpl - Obtaining JDBC connection 15:40:48 [main] DEBUG o.h.e.j.i.LogicalConnectionImpl - Obtained JDBC connection 15:40:48 [main] DEBUG o.h.e.t.i.j.JdbcTransaction - initial autocommit status: true 15:40:48 [main] DEBUG o.h.e.t.i.j.JdbcTransaction - disabling autocommit 15:40:48 [main] DEBUG o.s.o.j.JpaTransactionManager - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@88f431d] 15:40:48 [main] INFO c.c.c.f.c.a.b.s.i.InstrumentIdentifierServiceImpl - Updating the status of Request Id's 15:40:48 [main] DEBUG org.hibernate.SQL - UPDATE REQUEST SET STATUS = ? , MESSAGE = ? WHERE ID = ? 15:40:48 [main] DEBUG o.s.o.j.JpaTransactionManager - Initiating transaction commit 15:40:48 [main] DEBUG o.s.o.j.JpaTransactionManager - Committing JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@628b6e47] 15:40:48 [main] DEBUG o.h.e.t.s.AbstractTransactionImpl - committing 15:40:48 [main] DEBUG o.h.e.t.i.j.JdbcTransaction - committed JDBC Connection 15:40:48 [main] DEBUG o.h.e.t.i.j.JdbcTransaction - re-enabling autocommit 15:40:48 [main] DEBUG o.s.o.j.JpaTransactionManager - Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@628b6e47] after transaction 15:40:48 [main] DEBUG o.s.o.j.EntityManagerFactoryUtils - Closing JPA EntityManager 15:40:48 [main] DEBUG o.h.e.j.i.LogicalConnectionImpl - Releasing JDBC connection 15:40:48 [main] DEBUG o.h.e.j.i.LogicalConnectionImpl - Released JDBC connection 15:40:48 [main] DEBUG o.s.o.j.JpaTransactionManager - Resuming suspended transaction after completion of inner transaction

Thank you!

1

1 Answers

1
votes

Typically this scenario is handled with a ChunkListener. The listener's beforeChunk is used to "tag" all of the items to be read, then the listener's afterChunk handles the subsequent update after the items have ben processed. Another approach is to use the StepExecutionListener to tag all of the items to be processed within the step.

With regards to what is occurring, it sounds like you're running into the issue of nested transactions. Since you have an outer transaction, the inner one won't get applied until the outer one commits.