Spring Batch Example in Spring boot - XML File to CSV File - Walking Techie

Blog about Java programming, Design Pattern, and Data Structure.

Tuesday, March 28, 2017

Spring Batch Example in Spring boot - XML File to CSV File

In this post, we will show you how to configure a Spring Batch job to read data from a XML file and write into CSV file.

Project structure

This is a directory structure of the standard gradle project.

Project dependencies

task wrapper(type: Wrapper) {
    gradleVersion = '3.2.1'
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

sourceCompatibility = 1.8

repositories {
    mavenLocal()
    mavenCentral()
}


dependencies {
    compile 'org.springframework:spring-oxm:4.3.7.RELEASE'
    compileOnly('org.projectlombok:lombok:1.16.12')
    compile('org.springframework.boot:spring-boot-starter-batch:1.5.2.RELEASE')
    testCompile('org.springframework.boot:spring-boot-starter-test:1.5.2.RELEASE')
}
buildscript {
    repositories {
        mavenLocal()
        jcenter()
    }
    dependencies {
        classpath "org.springframework.boot:spring-boot-gradle-plugin:1.5.2.RELEASE"
    }
}

application.properties file

#empty

Spring Batch Jobs

XML file

<?xml version="1.0" encoding="UTF-8" ?>
<students>
  <student>
    <rollNo>100</rollNo>
    <name>Walking Techie</name>
    <department>CS</department>
  </student>
  <student>
    <rollNo>101</rollNo>
    <name>John Doe</name>
    <department>CS</department>
  </student>
  <student>
    <rollNo>102</rollNo>
    <name>Sachin Tendulkar</name>
    <department>CS</department>
  </student>
</students>

Create a job which will read XML file and write into CSV file.

package com.walking.techie.xmltocsv.jobs;

import com.walking.techie.xmltocsv.model.Student;
import com.walking.techie.xmltocsv.processor.StudentProcessor;
import java.util.HashMap;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor;
import org.springframework.batch.item.file.transform.DelimitedLineAggregator;
import org.springframework.batch.item.xml.StaxEventItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.oxm.Unmarshaller;
import org.springframework.oxm.xstream.XStreamMarshaller;

@Configuration
@EnableBatchProcessing
public class BatchConfiguration {

  @Autowired
  private JobBuilderFactory jobBuilderFactory;
  @Autowired
  private StepBuilderFactory stepBuilderFactory;


  @Bean
  public Job XmlToCsvJob() {
    return jobBuilderFactory.get("XmlToCsvJob").flow(step1()).end().build();
  }

  @Bean
  public Step step1() {
    return stepBuilderFactory.get("step1").<Student, Student>chunk(10).reader(reader())
        .writer(writer()).processor(processor()).build();
  }

  @Bean
  public StudentProcessor processor() {
    return new StudentProcessor();
  }

  @Bean
  public StaxEventItemReader<Student> reader() {
    StaxEventItemReader<Student> reader = new StaxEventItemReader<>();
    reader.setResource(new ClassPathResource("student.xml"));
    reader.setFragmentRootElementName("student");
    reader.setUnmarshaller(unMarshaller());
    return reader;
  }

  public Unmarshaller unMarshaller() {
    XStreamMarshaller unMarshal = new XStreamMarshaller();
    unMarshal.setAliases(new HashMap<String, Class>() {{
      put("student", Student.class);
    }});
    return unMarshal;
  }

  @Bean
  public FlatFileItemWriter<Student> writer() {
    FlatFileItemWriter<Student> writer = new FlatFileItemWriter<>();
    writer.setResource(new FileSystemResource("csv/student.csv"));
    writer.setLineAggregator(new DelimitedLineAggregator<Student>() {{
      setDelimiter(",");
      setFieldExtractor(new BeanWrapperFieldExtractor<Student>() {{
        setNames(new String[]{"rollNo", "name", "department"});
      }});
    }});
    return writer;
  }
}

Map XML file values to Student object and write to CSV file.

A Java model class

package com.walking.techie.xmltocsv.model;

import lombok.Data;
import lombok.ToString;

@Data
@ToString
public class Student {

  private Integer rollNo;
  private String name;
  private String department;
}

A custom student processor class that will process each and every Student object.

package com.walking.techie.xmltocsv.processor;

import com.walking.techie.xmltocsv.model.Student;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.item.ItemProcessor;

@Slf4j
public class StudentProcessor implements ItemProcessor<Student, Student> {

  @Override
  public Student process(Student item) throws Exception {
    log.info("Student processed : " + item);
    return item;
  }
}

Run Application

package com.walking.techie;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class Application {

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

Output

Output of the application will store in csv/student.csv
100,Walking Techie,CS
101,John Doe,CS
102,Sachin Tendulkar,CS

output in console

2017-03-26 18:04:42.769  INFO 4272 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [FlowJob: [name=CsvToXmlJob]] launched with the following parameters: [{}]
2017-03-26 18:04:42.786  INFO 4272 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [step1]
2017-03-26 18:04:42.873  INFO 4272 --- [           main] c.w.t.x.processor.StudentProcessor       : Student processed : Student(rollNo=100, name=Walking Techie, department=CS)
2017-03-26 18:04:42.874  INFO 4272 --- [           main] c.w.t.x.processor.StudentProcessor       : Student processed : Student(rollNo=101, name=John Doe, department=CS)
2017-03-26 18:04:42.874  INFO 4272 --- [           main] c.w.t.x.processor.StudentProcessor       : Student processed : Student(rollNo=102, name=Sachin Tendulkar, department=CS)
2017-03-26 18:04:42.887  INFO 4272 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [FlowJob: [name=CsvToXmlJob]] completed with the following parameters: [{}] and the following status: [COMPLETED]

Note : This code has been compiled and run on mac notebook and intellij IDEA.

2 comments :

  1. Hi,
    Thank for the nice work.I need the code for read the data from oracle database and write it to xls file using spring batch.
    Thanks

    ReplyDelete
    Replies
    1. Hi,
      Thank you for visiting this blog. You can refer to the this example it can help you.
      http://walkingtechie.blogspot.com/2017/03/spring-batch-mysql-to-xml-file.html
      I suggest to do the all the example given in this list http://walkingtechie.blogspot.in/2017/03/spring-batch-with-spring-boot.html

      Delete