욱'S 노트

Spring Batch - 시작하기 본문

Programming/Spring Batch

Spring Batch - 시작하기

devsun 2015. 1. 16. 10:38

오늘은 스프링 배치를 처음으로 알아보도록 하겠다. 흠 요즘 일은 안하고 너무 리서치만 하는게 아닌가 싶다. 근데 지금이 딱 좋은게 아닐까 스킬업을 하기엔..ㅋ 일단 다음과 같이 pom파일을 만들어 보자. 아래와 같은 디펜던시를 가지고 진행을 하겠다.


<?xml version="1.0" encoding="UTF-8"?>
<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>org.springframework</groupId>
<artifactId>spring-batch-test</artifactId>
<version>0.1.0-SNAPSHOT</version>
<properties>
<jdk.version>1.6</jdk.version>
<spring.version>4.0.5.RELEASE</spring.version>
<spring.batch.version>3.0.2.RELEASE</spring.batch.version>
<junit.version>4.11</junit.version>
</properties>
<dependencies>
<!-- Spring XML to/back object -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
</dependency>

<!-- Spring Batch dependencies -->
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
<version>${spring.batch.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-infrastructure</artifactId>
<version>${spring.batch.version}</version>
</dependency>

<!-- Spring Batch unit test -->
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<version>${spring.batch.version}</version>
</dependency>

<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

일반적으로 배치 작업 프로세스를 간단하게 생각해보면 입력->프로세스->출력 이다.

아래와 같이 spring bean definition 파일을 작성하자.


<?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"
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">

<batch:job id="sampleJob">
<batch:step id="step01">
<batch:tasklet>
<batch:chunk reader="cvsItemReader" writer="xmlItemWriter"
processor="itemProcesser" commit-interval="1"/>
</batch:tasklet>
</batch:step>
</batch:job>

<bean id="cvsItemReader" class="org.springframework.batch.item.file.FlatFileItemReader">
<property name="resource" value="classpath:cvs/input/report.csv"/>
<property name="lineMapper" ref="lineMapper"/>
</bean>

<bean id="lineMapper" 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,sales,qty,staffName,date"/>
</bean>
</property>
<property name="fieldSetMapper">
<bean class="hello.ReportFieldSetMapper"/>
</property>
</bean>

<bean id="itemProcesser" class="hello.CustomItemProcessor"/>

<bean id="xmlItemWriter" class="org.springframework.batch.item.xml.StaxEventItemWriter">
<property name="resource" value="file:xml/output/report.xml" />
<property name="marshaller" ref="reportMarshaller" />
<property name="rootTagName" value="report" />
</bean>

<bean id="reportMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>hello.Report</value>
</list>
</property>
</bean>

<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 class="org.springframework.batch.test.JobLauncherTestUtils"/>

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


먼저 적정한 위치에 입력파일을 만든다. sample.csv의 내용은 다음과 같다.


1001,"213,100",980,"mkyong", 29/7/2013
1002,"320,200",1080,"staff 1", 30/7/2013
1003,"342,197",1200,"staff 2", 31/7/2013


cvsItemReader를 통해서 읽어들이게 되고 해당 파일을 조작하기 쉽도록 도메인 객체를 하나 만들자. 그리고 읽어들인 fieldSet을 도메인 객체로 변환하는 Mapper클래스도 하나 만들어 보자.


package hello;


import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.math.BigDecimal;
import java.util.Date;

@XmlRootElement(name = "record")
public class Report {

private int id;
private BigDecimal sales;
private int qty;
private String staffName;
private Date date;

@XmlAttribute(name = "id")
public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

@XmlElement(name = "sales")
public BigDecimal getSales() {
return sales;
}

public void setSales(BigDecimal sales) {
this.sales = sales;
}

@XmlElement(name = "qty")
public int getQty() {
return qty;
}

public void setQty(int qty) {
this.qty = qty;
}

@XmlElement(name = "staffName")
public String getStaffName() {
return staffName;
}

public void setStaffName(String staffName) {
this.staffName = staffName;
}

public Date getDate() {
return date;
}

public void setDate(Date date) {
this.date = date;
}

@Override
public String toString() {
return "Report [id=" + id + ", sales=" + sales
+ ", qty=" + qty + ", staffName=" + staffName + "]";
}

}


package hello;

import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.validation.BindException;

import java.text.ParseException;
import java.text.SimpleDateFormat;


/**
* Created by devsun on 15. 1. 15..
*/
public class ReportFieldSetMapper implements FieldSetMapper<Report> {
private SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");

@Override
public Report mapFieldSet(FieldSet fieldSet) throws BindException {

Report report = new Report();
report.setId(fieldSet.readInt("id"));
report.setSales(fieldSet.readBigDecimal("sales"));
report.setQty(fieldSet.readInt("qty"));
report.setStaffName(fieldSet.readString("staffName"));

//default format yyyy-MM-dd
//fieldSet.readDate(4);
String date = fieldSet.readString("date");

try {
report.setDate(dateFormat.parse(date));
} catch (ParseException e) {
e.printStackTrace();
}

return report;

}
}


다음으로 만들 클래스를 프로세서 클래스이다. 입력된 데이터를 출력할 데이터로 가공하는 부분이다. 일단 여기에서는 특별히 수행할 내용이 없으므로 아무런 기능없는 클래스를 만들겠다.


package hello;

import org.springframework.batch.item.ItemProcessor;

/**
* Created by devsun on 15. 1. 15..
*/
public class CustomItemProcessor implements ItemProcessor<Report, Report> {
@Override
public Report process(Report report) throws Exception {
return report;
}
}


출력에 사용될 빈은 xmlItemWriter이다. 해당 빈은 xml 어노테이션 정보를 이용하여, 도에민 객체를 xml로 변환하는 역할을 수행한다. 위에 설정이 참고하기 바란다.


마지막으로 테스트를 수행하기 위한 런쳐 클래스를 생성하도록 하겠다. 어플리케이션을 로딩하고 


package hello;

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.support.ClassPathXmlApplicationContext;

/**
* Created by devsun on 15. 1. 15..
*/
public class Application {
public static void main(String[] args) {
String[] springConfig =
{
"classpath:spring-context.xml"
};

ApplicationContext context =
new ClassPathXmlApplicationContext(springConfig);

JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
Job job = (Job) context.getBean("sampleJob");

try {
JobExecution execution = jobLauncher.run(job, new JobParameters());
System.out.println("Exit Status : " + execution.getStatus());
} catch (Exception e) {
e.printStackTrace();
}

System.out.println("Done");
}
}


수행결과는 다음과 같다.


<?xml version="1.0" encoding="UTF-8"?><report><record id="1001"><date>2013-07-29T00:00:00+09:00</date><qty>980</qty><sales>213100</sales><staffName>mkyong</staffName></record><record id="1002"><date>2013-07-30T00:00:00+09:00</date><qty>1080</qty><sales>320200</sales><staffName>staff 1</staffName></record><record id="1003"><date>2013-07-31T00:00:00+09:00</date><qty>1200</qty><sales>342197</sales><staffName>staff 2</staffName></record></report>



참고자료 : http://www.mkyong.com/



'Programming > Spring Batch' 카테고리의 다른 글

Spring Batch - 작업실행  (0) 2015.01.22
Spring Batch - JobRepository 구성하기  (0) 2015.01.22
Spring Batch - 작업정의  (1) 2015.01.22
Spring Batch - 도메인  (0) 2015.01.21
Spring Batch - 소개  (0) 2015.01.16
Comments