@Test
 // BATCH-1804
 public void testWriteRetryOnNonSkippableException() throws Exception {
   SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
   retryPolicy.setMaxAttempts(2);
   batchRetryTemplate.setRetryPolicy(retryPolicy);
   processor.setWriteSkipPolicy(
       new LimitCheckingItemSkipPolicy(
           1,
           Collections.<Class<? extends Throwable>, Boolean>singletonMap(
               IllegalArgumentException.class, true)));
   processor.setItemWriter(
       new ItemWriter<String>() {
         public void write(List<? extends String> items) throws Exception {
           if (items.contains("fail")) {
             throw new IllegalArgumentException("Expected Exception!");
           }
           if (items.contains("2")) {
             throw new RuntimeException("Expected Non-Skippable Exception!");
           }
         }
       });
   Chunk<String> inputs = new Chunk<String>(Arrays.asList("3", "fail", "2"));
   try {
     processor.process(contribution, inputs);
     fail("Expected IllegalArgumentException");
   } catch (IllegalArgumentException e) {
     assertEquals("Expected Exception!", e.getMessage());
   }
   try {
     // first retry
     processor.process(contribution, inputs);
     fail("Expected IllegalArgumentException");
   } catch (IllegalArgumentException e) {
     assertEquals("Expected Exception!", e.getMessage());
   }
   // retry exhausted, now scanning
   processor.process(contribution, inputs);
   try {
     // skip on this attempt
     processor.process(contribution, inputs);
     fail("Expected IllegalArgumentException");
   } catch (IllegalArgumentException e) {
     assertEquals("Expected Exception!", e.getMessage());
   }
   try {
     // should retry
     processor.process(contribution, inputs);
     fail("Expected RuntimeException");
   } catch (RetryException e) {
     throw e;
   } catch (RuntimeException e) {
     assertEquals("Expected Non-Skippable Exception!", e.getMessage());
   }
   assertEquals(1, contribution.getSkipCount());
   assertEquals(1, contribution.getWriteCount());
   assertEquals(0, contribution.getFilterCount());
 }
 @Test
 public void testWriteRetryOnTwoExceptions() throws Exception {
   SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
   retryPolicy.setMaxAttempts(2);
   batchRetryTemplate.setRetryPolicy(retryPolicy);
   processor.setWriteSkipPolicy(new AlwaysSkipItemSkipPolicy());
   processor.setItemWriter(
       new ItemWriter<String>() {
         public void write(List<? extends String> items) throws Exception {
           if (items.contains("fail")) {
             throw new IllegalArgumentException("Expected Exception!");
           }
         }
       });
   Chunk<String> inputs = new Chunk<String>(Arrays.asList("3", "fail", "fail", "4"));
   try {
     processor.process(contribution, inputs);
     fail("Expected RuntimeException");
   } catch (RuntimeException e) {
     assertEquals("Expected Exception!", e.getMessage());
   }
   try {
     // first retry
     processor.process(contribution, inputs);
     fail("Expected RuntimeException");
   } catch (RuntimeException e) {
     assertEquals("Expected Exception!", e.getMessage());
   }
   // retry exhausted, now scanning
   processor.process(contribution, inputs);
   try {
     // skip on this attempt
     processor.process(contribution, inputs);
     fail("Expected RuntimeException");
   } catch (RuntimeException e) {
     assertEquals("Expected Exception!", e.getMessage());
   }
   try {
     // 2nd exception detected
     processor.process(contribution, inputs);
     fail("Expected RuntimeException");
   } catch (RuntimeException e) {
     assertEquals("Expected Exception!", e.getMessage());
   }
   // still scanning
   processor.process(contribution, inputs);
   assertEquals(2, contribution.getSkipCount());
   assertEquals(2, contribution.getWriteCount());
   assertEquals(0, contribution.getFilterCount());
 }