Spring Boot + Spring Batch Job Parameters (2021) Hello World Example | CodeUsingJava






















Spring Boot + Spring Batch Job Parameters (2021) Hello World Example

In this tutorial we will be implementing how the job parameters can be passed at runtime with the help of an example.
Spring Batch is one of the open-source framework available for batch processing.
A batch job is a combination of reading input, processing the data and finally presenting the processed data in the form of output. Job Parameters can be defined as the data that are provided for a job to get started. They are in the form of key-value pairs. Different instances of a job are differentiated on the basis of job parameters. To access the job parameter, Spring Expression Language can be used.

Table Of Contents :


In this example, a record of persons is present in the xml file. The person having account balance less than that of minimum account balance i.e. 1000, their data will be transferred to the csv file.
The names are passed from xml file to csv file with the use of JobParameters to JobLauncher.
The flow between the application controller, the Job Launcher and the Job is described as follows:-
Spring Boot Job Launcher

Here I would be passing the names of xml and csv files as job parameters.
  • This will be the standard directory layout for maven project structure-
    Spring Boot Maven Project
    We need to start by creating a Maven pom.xml(Project Object Model) file. The pom.xml file contains the project configuration details.
    	<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<groupId>SpringBatchJobParam</groupId>
    	<artifactId>SpringBatchJobParam</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<dependencies>
    		  <dependency>
    			  <groupId>org.springframework</groupId>
    			  <artifactId>spring-core</artifactId>
    			  <version>4.3.5.RELEASE</version>
    		  </dependency>
    		  
    		  <dependency>
    			  <groupId>org.springframework.batch</groupId>
    			  <artifactId>spring-batch-core</artifactId>
    			  <version>3.0.7.RELEASE</version>
    		  </dependency>
    		  
    				  <!-- Spring XML to/back object -->
    		  <dependency>
    			  <groupId>org.springframework</groupId>
    			  <artifactId>spring-oxm</artifactId>
    			  <version>4.3.5.RELEASE</version>
    		  </dependency>
    	</dependencies>
      </project>
    	
    
    Under src/main/resources, create a new folder xml and then create a xml file named AllPersonDetail.xml.
    	<?xml version="1.0" encoding="UTF-8" ?>
    <Bank>
        <person personId="1">
            <name>A</name>
            <balance>3334</balance>
        </person>
        <person personId="2">
            <name>B</name>
            <balance>1099</balance>
            <dob>26/7/1983</dob>
            <income>100,999</income>
        </person>
         <person personId="3">
            <name>Z</name>
            <balance>400</balance>
        </person>
        <person personId="4">
            <name>B</name>
            <balance>900</balance>
            <dob>26/7/1983</dob>
            <income>100,999</income>
        </person>
        </Bank>
    
    Creating the model class for smooth converting spring bean into to csvfile.
    @XmlElement is used here for mapping with xml schema.An xml document can have multiple xml element.
    @XmlAttribute is used here for defining properties in xml schema.
    @XmlRootElement denotes the root element of the xml file.
    	package com.codeusingjava.model;
    
    	import javax.xml.bind.annotation.XmlAttribute;
    	import javax.xml.bind.annotation.XmlElement;
    	import javax.xml.bind.annotation.XmlRootElement;
    	
    	@XmlRootElement(name="person")
    	public class Person {
    	
    			private int personId;
    			private String name;
    			private int balance;
    	
    			@XmlAttribute(name = "personId")
    			public int getPersonId() {
    				return personId;
    			}
    	
    			public void setPersonId(int personId) {
    				this.personId = personId;
    			}
    	
    			@XmlElement(name = "name")
    			public String getName() {
    				return name;
    			}
    			
    			public void setName(String name) {
    				this.name = name;
    			}
    	
    			@XmlElement(name = "balance")
    			public int getBalance() {
    				return balance;
    			}
    	
    			public void setBalance(int balance) {
    				this.balance = balance;
    			}
    	
    	
    	}
    	
    

    Here the job parameters are defined in the form of key-value pairs and then passed to job launcher.
    package com.codeusingjava.main;
    
    import org.springframework.batch.core.Job;
    import org.springframework.batch.core.JobExecution;
    import org.springframework.batch.core.JobParameters;
    import org.springframework.batch.core.JobParametersBuilder;
    import org.springframework.batch.core.launch.JobLauncher;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MainApplication {
    
    	public static void main(String[] args) {
    
    
    		ApplicationContext context = 
    				new ClassPathXmlApplicationContext("config/personData.xml","config/appcontext.xml");
    		
    		JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
    		Job job = (Job) context.getBean("totalPersonReport");
    
    		try {
    			
    			JobParametersBuilder jobBuilder= new JobParametersBuilder();
    			jobBuilder.addString("lowbalancepersons", "SelectedPersons");
    			jobBuilder.addString("alldetailsfileName","AllPersonDetail");
    			JobParameters jobParameters =jobBuilder.toJobParameters();
    			JobExecution execution = jobLauncher.run(job, jobParameters);
    			System.out.println("Completion Status : " + execution.getStatus());
    
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    
    		System.out.println("Done");
    
    	}
    	
    }
    
    
    Creating the processor class.It filters the person having less balance then minimum value.
    The processor class reads each and every data element, then processes the data and finally writes the processed record in the writer.
    	package com.codeusingjava.processor;
    
    	import org.springframework.batch.item.ItemProcessor;
    	import com.codeusingjava.model.Person;
    	public class SelectedPersonsReportProcessor implements ItemProcessor<Person, Person> {
    	
    		public Person process(Person item) throws Exception {
    			
    			if(item.getBalance() >1000){
    				return null; // null = ignore this object
    			}
    			return item;
    		}		
    	}
    		
    
    Inside src/main/resources, create a new folder named config and create a class named appcontext.xml
    	<beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="
    		http://www.springframework.org/schema/beans 
    		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
    
    	<bean id="jobRepository"
    		class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
    		<property name="transactionManager" ref="transactionManager" />
    	</bean>
     	
    	<bean id="transactionManager"
    		class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
    	 
    	<bean id="jobLauncher"
    		class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
    		<property name="jobRepository" ref="jobRepository" />
    	</bean>
    
    </beans>
    
    
    
    Create another class inside config folder named personData.xml
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:batch="http://www.springframework.org/schema/batch" xmlns:task="http://www.springframework.org/schema/task"
    	xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://www.springframework.org/schema/batch
    		http://www.springframework.org/schema/batch/spring-batch-2.2.xsd
    		http://www.springframework.org/schema/beans 
    		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    		http://www.springframework.org/schema/util 
    		http://www.springframework.org/schema/util/spring-util-3.2.xsd">
    
    	<batch:job id="totalPersonReport">
    		<batch:step id="step1">
    			<batch:tasklet>
    				<batch:chunk reader="xmlItemReader" writer="cvsFileItemWriter" processor="selectedPersonsReportProcessor"
    					commit-interval="1">
    				</batch:chunk>
    			</batch:tasklet>
    		</batch:step>
    	</batch:job>
    
    	<bean id="selectedPersonsReportProcessor" class="com.codeusingjava.processor.SelectedPersonsReportProcessor" scope="step"/>
    
    	<bean id="xmlItemReader" class="org.springframework.batch.item.xml.StaxEventItemReader" scope="step">
    		<property name="fragmentRootElementName" value="person" />
    		<property name="resource" value="classpath:xml/#{jobParameters['alldetailsfileName']}.xml" />
    		<property name="unmarshaller" ref="reportUnmarshaller" />
    	</bean>
    
    	<!-- Read and map values to object, via jaxb2 -->
    	<bean id="reportUnmarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
    		<property name="classesToBeBound">
    			<list>
    				<value>com.codeusingjava.model.Person</value>
    			</list>
    		</property>
    	</bean>
    
    	<bean id="cvsFileItemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter" scope="step">
    
    		<!-- write to this csv file -->
    		<property name="shouldDeleteIfExists" value="true" />
     		<property name="resource"
          value="file:csv/#{jobParameters['lowbalancepersons']}.csv" />
    		<property name="lineAggregator">
    			<bean
    				class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
    				<property name="delimiter" value="," />
    				<property name="fieldExtractor">
    					<bean
    						class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
    						<property name="names" value="personId,name,balance" />
    					</bean>
    				</property>
    			</bean>
    		</property>
    
    	</bean>
    
    </beans>
    
If we now run the application as Run as->Java Application, we get the output as follows:-
Spring Boot Batch Output
To see the xml processed records into a csv file , see the csv file created as SelectedPersons.csv in the csv folder
Spring Boot Batch Example

Downloads-

Spring Boot + Spring Batch Job Parameters Example