Changing Skip Policy to out of box provided skip policies

In this post under Spring Batch, I will explain how to change skip policy to one of out of the box provided skip policies.

Whenever we use the “skip-limit” attribute and “skippable-exception-classes” element as shown below at line 4 and 5

   <batch:job id="importEmployees">
      <batch:step id="readWriteEmployees">
           <batch:tasklet>
               <batch:chunk reader="reader" writer="writer" commit-interval="50" skip-limit="200">
                   <batch:skippable-exception-classes>
                       <batch:include class="org.springframework.batch.item.file.FlatFileParseException"/>
                   </batch:skippable-exception-classes>
               </batch:chunk>
               <batch:listeners>
                  <batch:listener ref="mySkipListener"/>
              </batch:listeners>
         </batch:tasklet>
      </batch:step>
 </batch:job>

Spring Batch internally uses “org.springframework.batch.core.step.skip.LimitCheckingItemSkipPolicy” implementation. This class is one of the out of the box provided skip policies. The others are

1) AlwaysSkipItemSkipPolicy
2) ExceptionClassifierSkipPolicy
3) NeverSkipItemSkipPolicy
4) CompositeSkipPolicy

As part of this example I will show you how to use “AlwaysSkipItemSkipPolicy”.

AlwaysSkipItemSkipPolicy class just skips records which throws exceptions (regardless of type of exception). There is no limit check and a way to specify for which specific exception to skip.

Below is the xml configuration

XML Snippet

<bean id="alwaysSkipItemSkipPolicy" class="org.springframework.batch.core.step.skip.AlwaysSkipItemSkipPolicy"/>

<batch:job id="importEmployees">
		<batch:step id="readWriteEmployees">
			<batch:tasklet>
				<batch:chunk reader="reader" writer="writer" commit-interval="50" skip-policy="alwaysSkipItemSkipPolicy"/>
			</batch:tasklet>
		</batch:step>
	</batch:job>

In the above xml snippet, at line 1 I create a bean definition for class “AlwaysSkipItemSkipPolicy” with id “alwaysSkipItemSkipPolicy”.

Then I refer to the bean “alwaysSkipItemSkipPolicy” using “skip-policy” attribute at line 6.

In this way, we can use skip policies other than LimitCheckingItemSkipPolicy.

Below is the complete xml code for your reference.

XML code

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:batch="http://www.springframework.org/schema/batch"
	   xmlns:jdbc="http://www.springframework.org/schema/jdbc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
						http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
						http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd">
	
	<bean id="employee" class="xml.package24.Employee" scope="prototype"/>
	
	<bean id="reader" class="org.springframework.batch.item.file.FlatFileItemReader">
		<property name="resource" value="file:EmployeeRecordsWithFileParseException.txt"/>
		<property name="lineMapper">
			<bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
				<property name="lineTokenizer">
					<bean class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
						<property name="names" value="id,name,status,salary"/>
					</bean>
				</property>
				<property name="fieldSetMapper">
					<bean class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
						<property name="prototypeBeanName" value="employee"/>
					</bean>
				</property>
			</bean>
		</property> 
	</bean>
	
	<bean id="writer" class="org.springframework.batch.item.file.FlatFileItemWriter">
		<property name="resource" value="file:FileOutput.txt"/>
		<property name="lineAggregator">
			<bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
				<property name="fieldExtractor">
					<bean class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
						<property name="names" value="id,name,status,salary"/>
					</bean>
				</property>
			</bean>
		</property>
	</bean>

	<bean id="alwaysSkipItemSkipPolicy" class="org.springframework.batch.core.step.skip.AlwaysSkipItemSkipPolicy"/>
	
	<batch:job id="importEmployees">
		<batch:step id="readWriteEmployees">
			<batch:tasklet>
				<batch:chunk reader="reader" writer="writer" commit-interval="50" skip-policy="alwaysSkipItemSkipPolicy"/>
			</batch:tasklet>
		</batch:step>
	</batch:job>

	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>

	<bean id="dataSource"
		  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="org.h2.Driver" />
		<property name="url" value="jdbc:h2:file:~/repository" />
		<property name="username" value="" />
		<property name="password" value="" />
	</bean>

	<!-- create job-meta tables automatically -->
	<jdbc:initialize-database data-source="dataSource">
		<jdbc:script
				location="org/springframework/batch/core/schema-drop-h2.sql" />
		<jdbc:script location="org/springframework/batch/core/schema-h2.sql" />
	</jdbc:initialize-database>

	<bean id="jobRepository"
		  class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
		<property name="dataSource" ref="dataSource"/>
		<property name="transactionManager" ref="transactionManager"/>
		<property name="databaseType" value="h2"/>
	</bean>

	<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.TaskExecutorJobLauncher">
		<property name="jobRepository" ref="jobRepository"/>
	</bean>
</beans>

Leave a comment