0

I've configured my Spring Batch app below:

<batch:job id="mPortRiskJob">
    <batch:step id="mPortRiskStep">
        <tasklet throttle-limit="10">
           <chunk reader="MPortRiskReader"  processor="MPortRiskProcessor" writer="MPortRiskWriter" commit-interval="10"
            skip-limit="1">
               <batch:skippable-exception-classes>
                   <include class="com.common.exception.ERDException"/>
               </batch:skippable-exception-classes>
           </chunk>
            <batch:no-rollback-exception-classes>
                <include class="com.common.exception.ERDException"/>
            </batch:no-rollback-exception-classes>
        </tasklet>
    </batch:step>   
    <batch:listeners>
        <batch:listener ref="MJobExecutionListener"/>
    </batch:listeners>    
</batch:job>

In my writer, I have a for-loop that inserts records into the database. The code looks like below:

for (String id : keylist) {
  try {
      insertRecord(id);
  } catch (Exception e) {
      throw new ERDException("Failure in write method", e);
  }
}

What I want is if, for instance, the first record throws a DuplicateKeyException, for that record to be skipped, and the next record to be inserted. What's happening is, when the ERDException is thrown, Spring Batch retries all the records, including the duplicate. I want it to discard that particular record and insert the others. Is there a way to accomplish that?

CNDyson
  • 1,687
  • 7
  • 28
  • 63

2 Answers2

0

Well since your exception is thrown in writer with commit-interval as 10 it is retrying all 10 records again because it needs to determine which record throws exception. Once it determines the record it will skip just that record and process others.

Please see this post.

Sushil Behera
  • 817
  • 6
  • 20
0

For anyone interested, I solved my problem by combining no-rollback-exception-classes with a skip-policy! I probably went a little overboard with defining my own skip policy - one of the out-of-the-box Spring policies would have been fine. See below:

<bean id="skipPolicy" class="com.trp.erd.batch.ERDSkipPolicy">

<batch:job id="midrPortRiskJob">
    <batch:step id="midrPortRiskStep">
        <tasklet throttle-limit="10">
           <chunk reader="MIDRPortRiskReader"  processor="MIDRPortRiskProcessor" writer="MIDRPortRiskWriter" commit-interval="10"
            skip-limit="1" skip-policy="skipPolicy">
               <batch:skippable-exception-classes>
                   <include class="com.trp.erd.common.exception.ERDException"/>
               </batch:skippable-exception-classes>
           </chunk>
            <batch:no-rollback-exception-classes>
                <include class="com.trp.erd.common.exception.ERDException"/>
            </batch:no-rollback-exception-classes>
        </tasklet>
    </batch:step>   
    <batch:listeners>
        <batch:listener ref="MIDRJobExecutionListener"/>
    </batch:listeners>    
</batch:job>

And the skip policy implementation:

public class ERDSkipPolicy implements SkipPolicy {

    @Override
    public boolean shouldSkip(Throwable t, int skipCount) {
        if (t instanceOf ERDException) {
            return true;
        }
    }    
}
CNDyson
  • 1,687
  • 7
  • 28
  • 63