title: spring batch: processor called twice after skip
body: <p>I have a defined a chunk with commit-interval as 10, skip-limit as 10. A processor class manipulates a field by applying some arithmetic operations. In processor class exception occurs for one of the records (say 6th record). After this, once again records from 1 to 5 are processed, 6th is skipped, 7-10 are processed and written to a XML (a custom XML writer class). Since the processor processes 1-5 records twice, the expected field value is wrong as it is calculated twice. Can you please suggest a solution to have the processor process the records only once, skip only the failed record and write the processed records to XML?</p>
  
  <p>Implemented a SkipListener with onSkipInProcess(), onSkipInRead(), onSkipInWrite(). But the output is still the same. </p>
  
  <p>jobconfig.xml</p>
  
  <pre><code>&lt;batch:job id="job"&gt;
      &lt;batch:step id="step"&gt;
          &lt;batch:tasklet&gt;
              &lt;batch:chunk reader="itemReader" writer="itemWriter" 
                  processor="itemProcessor" commit-interval="10" skip-limit="5" retry-limit="0" &gt;
                  &lt;batch:skippable-exception-classes&gt;
                      &lt;batch:include class="java.lang.Exception"/&gt;
                  &lt;/batch:skippable-exception-classes&gt;
                  &lt;batch:listeners&gt;
                      &lt;batch:listener ref="skipListener" /&gt;
                  &lt;/batch:listeners&gt;
              &lt;/batch:chunk&gt;
          &lt;/batch:tasklet&gt;
      &lt;/batch:step&gt;
  &lt;/batch:job&gt;  
  &lt;bean id="itemWriter" class="a.b.XWriter" scope="step"/&gt;
  &lt;bean id="skipListener" class="a.b.SkipListener"/&gt;
  &lt;bean id="itemProcessor" class="a.b.XProcessor" scope="step"/&gt;
  &lt;bean id="itemReader" class="a.b.XReader"/&gt;
  </code></pre>
  
  <p>ItemReader class:</p>
  
  <pre><code>public class XReader implements ItemReader {
  @Autowired
  private XRepository classDao;
  
  private List lst = new ArrayList();
  private int index= 0;
  
  public Object read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
      if (lst.isEmpty()) {
             lst = classDao.findAll();
      } 
      if (index &lt; lst.size()) {
          return lst.get(index++);
      } else return null;
  
  }
  }
  </code></pre>
  
  <p>ItemProcessor class:</p>
  
  <pre><code>public class XProcessor&lt;T&gt; implements ItemProcessor&lt;T, T&gt; {
  public Object process(Object item) throws Exception {
      // logic here
  }
  </code></pre>
  
  <p>ItemWriter class:</p>
  
  <pre><code>public class XWriter &lt;T&gt; implements ItemWriter&lt;T&gt; {
  public void write(List&lt;? extends T&gt; items) throws Exception {
      // logic here to write to XML
  }}
  </code></pre>
  
  <p>SkipListener class:</p>
  
  <pre><code>public class SkipListener&lt;T,S&gt; implements org.springframework.batch.core.SkipListener&lt;T, S&gt; {
  
  public void onSkipInProcess(T arg0, Throwable arg1) {
  }
  
  public void onSkipInRead(Throwable arg0) {
  }
  
  public void onSkipInWrite(S arg0, Throwable arg1) {
  }
  
  }
  </code></pre>