diff --git a/spring-batch-intro/.classpath b/spring-batch-intro/.classpath
new file mode 100644
index 0000000000..395dbde027
--- /dev/null
+++ b/spring-batch-intro/.classpath
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-batch-intro/.project b/spring-batch-intro/.project
new file mode 100644
index 0000000000..032f8a9541
--- /dev/null
+++ b/spring-batch-intro/.project
@@ -0,0 +1,23 @@
+
+
+ spring-batch-intro
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+
+
diff --git a/spring-batch-intro/pom.xml b/spring-batch-intro/pom.xml
new file mode 100644
index 0000000000..28d48c594e
--- /dev/null
+++ b/spring-batch-intro/pom.xml
@@ -0,0 +1,44 @@
+
+ 4.0.0
+
+ org.baeldung
+ spring-batch-intro
+ 0.1-SNAPSHOT
+ jar
+
+ spring-batch-intro
+ http://maven.apache.org
+
+
+ UTF-8
+ 4.2.0.RELEASE
+ 3.0.5.RELEASE
+ 3.8.11.2
+
+
+
+
+
+ org.xerial
+ sqlite-jdbc
+ ${sqlite.version}
+
+
+ org.springframework
+ spring-oxm
+ ${spring.version}
+
+
+ org.springframework
+ spring-jdbc
+ ${spring.version}
+
+
+ org.springframework.batch
+ spring-batch-core
+ ${spring.batch.version}
+
+
+
+
diff --git a/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/App.java b/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/App.java
new file mode 100644
index 0000000000..d6af37595c
--- /dev/null
+++ b/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/App.java
@@ -0,0 +1,36 @@
+package org.baeldung.spring_batch_intro;
+
+import org.springframework.batch.core.Job;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.launch.JobLauncher;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+
+public class App {
+ public static void main(String[] args) {
+ // Spring Java config
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
+ context.register(SpringConfig.class);
+ context.register(SpringBatchConfig.class);
+ context.refresh();
+
+ // Spring xml config
+ // ApplicationContext context = new ClassPathXmlApplicationContext(
+ // "spring-batch-intro.xml");
+
+ JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
+ Job job = (Job) context.getBean("firstBatchJob");
+ System.out.println("Starting the batch job");
+ try {
+ JobExecution execution = jobLauncher.run(job, new JobParameters());
+ System.out.println("Job Status : " + execution.getStatus());
+ System.out.println("Job succeeded");
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.out.println("Job failed");
+ }
+ }
+}
\ No newline at end of file
diff --git a/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/SpringBatchConfig.java b/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/SpringBatchConfig.java
new file mode 100644
index 0000000000..a024cbc04e
--- /dev/null
+++ b/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/SpringBatchConfig.java
@@ -0,0 +1,93 @@
+package org.baeldung.spring_batch_intro;
+
+import java.net.MalformedURLException;
+import java.text.ParseException;
+
+import org.baeldung.spring_batch_intro.model.Transaction;
+import org.baeldung.spring_batch_intro.service.CustomItemProcessor;
+import org.baeldung.spring_batch_intro.service.RecordFieldSetMapper;
+import org.springframework.batch.core.Job;
+import org.springframework.batch.core.Step;
+import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
+import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
+import org.springframework.batch.item.ItemProcessor;
+import org.springframework.batch.item.ItemReader;
+import org.springframework.batch.item.ItemWriter;
+import org.springframework.batch.item.UnexpectedInputException;
+import org.springframework.batch.item.file.FlatFileItemReader;
+import org.springframework.batch.item.file.mapping.DefaultLineMapper;
+import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
+import org.springframework.batch.item.xml.StaxEventItemWriter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.io.Resource;
+import org.springframework.oxm.Marshaller;
+import org.springframework.oxm.jaxb.Jaxb2Marshaller;
+
+public class SpringBatchConfig {
+ @Autowired
+ private JobBuilderFactory jobs;
+
+ @Autowired
+ private StepBuilderFactory steps;
+
+ @Value("input/record.csv")
+ private Resource inputCsv;
+
+ @Value("file:xml/output.xml")
+ private Resource outputXml;
+
+ @Bean
+ public ItemReader itemReader()
+ throws UnexpectedInputException, ParseException {
+ FlatFileItemReader reader = new FlatFileItemReader();
+ DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
+ String[] tokens = { "username", "userid", "transactiondate", "amount" };
+ tokenizer.setNames(tokens);
+ reader.setResource(inputCsv);
+ DefaultLineMapper lineMapper = new DefaultLineMapper();
+ lineMapper.setLineTokenizer(tokenizer);
+ lineMapper.setFieldSetMapper(new RecordFieldSetMapper());
+ reader.setLinesToSkip(1);
+ reader.setLineMapper(lineMapper);
+ return reader;
+ }
+
+ @Bean
+ public ItemProcessor itemProcessor() {
+ return new CustomItemProcessor();
+ }
+
+ @Bean
+ public ItemWriter itemWriter(Marshaller marshaller)
+ throws MalformedURLException {
+ StaxEventItemWriter itemWriter = new StaxEventItemWriter();
+ itemWriter.setMarshaller(marshaller);
+ itemWriter.setRootTagName("transactionRecord");
+ itemWriter.setResource(outputXml);
+ return itemWriter;
+ }
+
+ @Bean
+ public Marshaller marshaller() {
+ Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
+ marshaller.setClassesToBeBound(new Class[] { Transaction.class });
+ return marshaller;
+ }
+
+ @Bean
+ protected Step step1(ItemReader reader,
+ ItemProcessor processor,
+ ItemWriter writer) {
+ return steps.get("step1"). chunk(10)
+ .reader(reader).processor(processor).writer(writer).build();
+ }
+
+ @Bean(name = "firstBatchJob")
+ public Job job(@Qualifier("step1") Step step1) {
+ return jobs.get("firstBatchJob").start(step1).build();
+ }
+
+}
diff --git a/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/SpringConfig.java b/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/SpringConfig.java
new file mode 100644
index 0000000000..91366d8721
--- /dev/null
+++ b/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/SpringConfig.java
@@ -0,0 +1,79 @@
+package org.baeldung.spring_batch_intro;
+
+import java.net.MalformedURLException;
+
+import javax.sql.DataSource;
+
+import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
+import org.springframework.batch.core.launch.JobLauncher;
+import org.springframework.batch.core.launch.support.SimpleJobLauncher;
+import org.springframework.batch.core.repository.JobRepository;
+import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
+import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.Resource;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+import org.springframework.jdbc.datasource.init.DataSourceInitializer;
+import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
+import org.springframework.transaction.PlatformTransactionManager;
+
+@Configuration
+@EnableBatchProcessing
+public class SpringConfig {
+
+ @Value("org/springframework/batch/core/schema-drop-sqlite.sql")
+ private Resource dropReopsitoryTables;
+
+ @Value("org/springframework/batch/core/schema-sqlite.sql")
+ private Resource dataReopsitorySchema;
+
+ @Bean
+ public DataSource dataSource() {
+ DriverManagerDataSource dataSource = new DriverManagerDataSource();
+ dataSource.setDriverClassName("org.sqlite.JDBC");
+ dataSource.setUrl("jdbc:sqlite:repository.sqlite");
+ return dataSource;
+ }
+
+ @Bean
+ public DataSourceInitializer dataSourceInitializer(DataSource dataSource)
+ throws MalformedURLException {
+ ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
+
+ databasePopulator.addScript(dropReopsitoryTables);
+ databasePopulator.addScript(dataReopsitorySchema);
+ databasePopulator.setIgnoreFailedDrops(true);
+
+ DataSourceInitializer initializer = new DataSourceInitializer();
+ initializer.setDataSource(dataSource);
+ initializer.setDatabasePopulator(databasePopulator);
+
+ return initializer;
+ }
+
+ private JobRepository getJobRepository() throws Exception {
+ JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
+ factory.setDataSource(dataSource());
+ factory.setTransactionManager(getTransactionManager());
+ // JobRepositoryFactoryBean's methods Throws Generic Exception,
+ // it would have been better to have a specific one
+ factory.afterPropertiesSet();
+ return (JobRepository) factory.getObject();
+ }
+
+ private PlatformTransactionManager getTransactionManager() {
+ return new ResourcelessTransactionManager();
+ }
+
+ public JobLauncher getJobLauncher() throws Exception {
+ SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
+ // SimpleJobLauncher's methods Throws Generic Exception,
+ // it would have been better to have a specific one
+ jobLauncher.setJobRepository(getJobRepository());
+ jobLauncher.afterPropertiesSet();
+ return jobLauncher;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/model/Transaction.java b/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/model/Transaction.java
new file mode 100644
index 0000000000..6e80298ff0
--- /dev/null
+++ b/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/model/Transaction.java
@@ -0,0 +1,56 @@
+package org.baeldung.spring_batch_intro.model;
+
+import java.util.Date;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@SuppressWarnings("restriction")
+@XmlRootElement(name = "transactionRecord")
+public class Transaction {
+ private String username;
+ private int userId;
+ private Date transactionDate;
+ private double amount;
+
+ /* getters and setters for the attributes */
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public int getUserId() {
+ return userId;
+ }
+
+ public void setUserId(int userId) {
+ this.userId = userId;
+ }
+
+ public Date getTransactionDate() {
+ return transactionDate;
+ }
+
+ public void setTransactionDate(Date transactionDate) {
+ this.transactionDate = transactionDate;
+ }
+
+ public double getAmount() {
+ return amount;
+ }
+
+ public void setAmount(double amount) {
+ this.amount = amount;
+ }
+
+ @Override
+ public String toString() {
+ return "Transaction [username=" + username + ", userId=" + userId
+ + ", transactionDate=" + transactionDate + ", amount=" + amount
+ + "]";
+ }
+
+}
diff --git a/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/service/CustomItemProcessor.java b/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/service/CustomItemProcessor.java
new file mode 100644
index 0000000000..baabe79409
--- /dev/null
+++ b/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/service/CustomItemProcessor.java
@@ -0,0 +1,13 @@
+package org.baeldung.spring_batch_intro.service;
+
+import org.baeldung.spring_batch_intro.model.Transaction;
+import org.springframework.batch.item.ItemProcessor;
+
+public class CustomItemProcessor implements
+ ItemProcessor {
+
+ public Transaction process(Transaction item) {
+ System.out.println("Processing..." + item);
+ return item;
+ }
+}
\ No newline at end of file
diff --git a/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/service/RecordFieldSetMapper.java b/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/service/RecordFieldSetMapper.java
new file mode 100644
index 0000000000..94f9e7d94e
--- /dev/null
+++ b/spring-batch-intro/src/main/java/org/baeldung/spring_batch_intro/service/RecordFieldSetMapper.java
@@ -0,0 +1,35 @@
+package org.baeldung.spring_batch_intro.service;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
+import org.baeldung.spring_batch_intro.model.Transaction;
+import org.springframework.batch.item.file.mapping.FieldSetMapper;
+import org.springframework.batch.item.file.transform.FieldSet;
+import org.springframework.validation.BindException;
+
+public class RecordFieldSetMapper implements FieldSetMapper {
+
+ public Transaction mapFieldSet(FieldSet fieldSet) throws BindException {
+
+ SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
+ Transaction transaction = new Transaction();
+ // you can either use the indices or custom names
+ // I personally prefer the custom names easy for debugging and
+ // validating the pipelines
+ transaction.setUsername(fieldSet.readString("username"));
+ transaction.setUserId(fieldSet.readInt("userid"));
+ transaction.setAmount(fieldSet.readDouble(3));
+ // Converting the date
+ String dateString = fieldSet.readString(2);
+ try {
+ transaction.setTransactionDate(dateFormat.parse(dateString));
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+
+ return transaction;
+
+ }
+
+}
diff --git a/spring-batch-intro/src/main/resources/input/record.csv b/spring-batch-intro/src/main/resources/input/record.csv
new file mode 100644
index 0000000000..e554becb2a
--- /dev/null
+++ b/spring-batch-intro/src/main/resources/input/record.csv
@@ -0,0 +1,4 @@
+username, user_id, transaction_date, transaction_amount
+devendra, 1234, 31/10/2015, 10000
+john, 2134, 3/12/2015, 12321
+robin, 2134, 2/02/2015, 23411
\ No newline at end of file
diff --git a/spring-batch-intro/src/main/resources/spring-batch-intro.xml b/spring-batch-intro/src/main/resources/spring-batch-intro.xml
new file mode 100644
index 0000000000..93606d232f
--- /dev/null
+++ b/spring-batch-intro/src/main/resources/spring-batch-intro.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.baeldung.spring_batch_intro.model.Transaction
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-batch-intro/src/main/resources/spring.xml b/spring-batch-intro/src/main/resources/spring.xml
new file mode 100644
index 0000000000..dea261c5e6
--- /dev/null
+++ b/spring-batch-intro/src/main/resources/spring.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-batch-intro/xml/output.xml b/spring-batch-intro/xml/output.xml
new file mode 100644
index 0000000000..acf4969341
--- /dev/null
+++ b/spring-batch-intro/xml/output.xml
@@ -0,0 +1 @@
+10000.02015-10-31T00:00:00+05:301234devendra12321.02015-12-03T00:00:00+05:302134john23411.02015-02-02T00:00:00+05:302134robin
\ No newline at end of file