title: Spring Batch Reader's cursor closed early in JTA transaction managed step
body: <p>The <em>working</em> configuration for the step in question is the following:</p>
  
  <ul>
  <li>Step, Spring Batch Job Repository, and business repositories (using various datasources) all use a JTA transaction manager.</li>
  <li>Step "myStep" uses a Jdbc Paging Item Reader.</li>
  <li>WebLogic, Oracle XE and/or EE</li>
  </ul>
  
  <p>I wanted to analyze the performance of the Jdbc <strong>Cursor</strong> Item Reader in "myStep", however after the first commit, the second chunk's first read would fail with <em>java.sql.SQLException: Result set already closed</em>.</p>
  
  <p>I suspected it might be JTA / XA driver closing the cursor for some reason, so I gave "myStep" a simple datasource transaction manager (on the datasource the reader was using), and the step was able to complete successfully. This isn't a solution, since this breaks transactionally integrity of the step.</p>
  
  <p>Should I be able to use a cursor reader inside of a JTA managed step (using the environment described below)? If so, what might be configured incorrectly on my end?</p>
  
  <p><strong>Environment</strong></p>
  
  <ul>
  <li>Transaction Manager:<code>&lt;bean id="myTransactionManager"
  class="org.springframework.transaction.jta.JtaTransactionManager"/&gt;</code></li>
  <li>Datasource Driver: OracleXADataSource JDBC 6 11.1.0.7.0</li>
  <li>WebLogic: 12.1.3.0.0</li>
  <li>Oracle DB 11g: Enterprise Edition 11.2.0.4.0</li>
  <li>OS: OSX or Linux</li>
  </ul>
  
  <p><strong>Config</strong></p>
  
  <pre><code>&lt;bean id="myTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/&gt;
  
  &lt;bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean"&gt;
      &lt;property name="jndiName" value="jdbc/myDataSource"/&gt;
      &lt;property name="proxyInterface" value="javax.sql.DataSource"/&gt;
  &lt;/bean&gt;
  
  &lt;batch:step id="myStep" job-repository="myJobRepositoryFactory"&gt;
      &lt;batch:tasklet transaction-manager="myTransactionManager"&gt;
          &lt;batch:chunk
                  reader="myReader"
                  processor="myProcessor"
                  writer="myWriter"
                  commit-interval="100"
                  processor-transactional="false"/&gt;
          &lt;batch:listeners&gt;
              &lt;batch:listener ref="myListener"/&gt;
          &lt;/batch:listeners&gt;
      &lt;/batch:tasklet&gt;
  &lt;/batch:step&gt;
  
  &lt;bean id="myReader" class="org.springframework.batch.item.database.JdbcCursorItemReader" scope="step"&gt;
      &lt;property name="dataSource" ref="myDataSource"/&gt;
      &lt;property name="sql" value="SELECT * FROM myHugeTable ORDER BY myColumn DESC"/&gt;
      &lt;property name="rowMapper"&gt;
          &lt;bean class="myRowMapper"/&gt;
      &lt;/property&gt;
  &lt;/bean&gt;
  </code></pre>
  
  <p><strong>Caught in the act</strong></p>
  
  <p>Below is the call stack of the result set being closed before the next chunk's read. Notice XA Connection closing all statements, which causes JDBC to close all results sets.</p>
  
  <pre><code>java.lang.Thread.State: RUNNABLE
    at weblogic.jdbc.wrapper.ResultSet.internalClose(ResultSet.java:178)
    at weblogic.jdbc.wrapper.Statement.closeAllResultSets(Statement.java:286)
    at weblogic.jdbc.wrapper.Statement.internalClose(Statement.java:395)
    at weblogic.jdbc.wrapper.Statement.internalClose(Statement.java:367)
    at weblogic.jdbc.wrapper.XAConnection.closeAllStatements(XAConnection.java:393)
    at weblogic.jdbc.wrapper.XAConnection.cleanup(XAConnection.java:406)
    at weblogic.jdbc.wrapper.XAConnection.releaseToPool(XAConnection.java:432)
    at weblogic.jdbc.jta.DataSource.removeTxAssoc(DataSource.java:1907)
    at weblogic.jdbc.jta.DataSource.prepare(DataSource.java:1090)
    at weblogic.transaction.internal.XAServerResourceInfo.prepare(XAServerResourceInfo.java:1408)
    at weblogic.transaction.internal.XAServerResourceInfo.prepare(XAServerResourceInfo.java:522)
    at weblogic.transaction.internal.ServerSCInfo.startPrepare(ServerSCInfo.java:411)
    at weblogic.transaction.internal.ServerTransactionImpl.localPrepare(ServerTransactionImpl.java:2709)
    at weblogic.transaction.internal.ServerTransactionImpl.globalPrepare(ServerTransactionImpl.java:2340)
    at weblogic.transaction.internal.ServerTransactionImpl.internalCommit(ServerTransactionImpl.java:300)
    at weblogic.transaction.internal.ServerTransactionImpl.commit(ServerTransactionImpl.java:260)
    at org.glassfish.transaction.TransactionManagerImplCommon.commit(TransactionManagerImplCommon.java:571)
    at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1021)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:150)
    at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:271)
    at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:77)
    at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368)
    at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
    at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
    at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:257)
    at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:198)
    at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148)
    at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64)
    at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:67)
    at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:165)
    at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144)
    at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:134)
    at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:304)
    at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
  </code></pre>