春のバッチの例 – CSVファイルへのXMLファイル
このチュートリアルでは、XMLファイル(
JAXB2`ライブラリ)を
csv`ファイルに読み込み、 `ItemProcessor`で書き込む前にレコードをフィルタするようにSpringバッチジョブを設定する方法を説明します。
使用されるツールとライブラリ
-
Maven 3
-
Eclipse 4.2
-
JDK 1.6
-
Spring Core 3.2.2.RELEASE
-
Spring Batch 2.2.0.RELEASE
-
Spring OXM 3.2.2.RELEASE
P.Sこの例 – XMLファイル(リーダー) – フィルタリング(itemProcessor) – CSV(ライター).
1.シンプルなJavaプロジェクト
{空} 1。 MavenでクイックスタートJavaプロジェクトを作成し、Eclipse IDEに変換してインポートします。
$ mvn archetype:generate -DgroupId=com.mkyong -DartifactId=SpringBatchExample3 -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
$ cd SpringBatchExample3/$ mvn eclipse:eclipse
プロジェクトの依存関係
`pom.xml`のすべてのプロジェクト依存関係を宣言します。
pom.xml
<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/maven-v4__0__0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mkyong</groupId>
<artifactId>SpringBatchExample</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>SpringBatchExample</name>
<url>http://maven.apache.org</url>
<properties>
<jdk.version>1.6</jdk.version>
<spring.version>3.2.2.RELEASE</spring.version>
<spring.batch.version>2.2.0.RELEASE</spring.batch.version>
</properties>
<dependencies>
<!-- Spring Core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 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>
</dependencies>
<build>
<finalName>spring-batch</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>false</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.プロジェクトのディレクトリ構造
最終的なプロジェクトの構造を見直し、次に何が起こるかを概観する。

4. XMLファイル
resources/xml/report.xml
<?xml version="1.0" encoding="UTF-8" ?>
<company>
<record refId="1001">
<name>mkyong</name>
<age>31</age>
<dob>31/8/1982</dob>
<income>200,000</income>
</record>
<record refId="1002">
<name>kkwong</name>
<age>30</age>
<dob>26/7/1983</dob>
<income>100,999</income>
</record>
<record refId="1003">
<name>joel</name>
<age>29</age>
<dob>21/8/1984</dob>
<income>1,000,000</income>
</record>
<record refId="1004">
<name>leeyy</name>
<age>29</age>
<dob>21/3/1984</dob>
<income>80,000.89</income>
</record>
</company>
5. XMLファイルを読む
この例では、XML値と属性をオブジェクトにマップするために `Jaxb2Marshaller`を使用します。
resources/spring/batch/jobs/job-report.xml
<!-- ...... -->
<bean id="xmlItemReader"
class="org.springframework.batch.item.xml.StaxEventItemReader">
<property name="fragmentRootElementName" value="record"/>
<property name="resource" value="classpath:xml/report.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.mkyong.model.Report</value>
</list>
</property>
</bean>
どのXML値がどのフィールドにマップされているかを知るために `Report`に注釈を付けます。
Report.java
package com.mkyong.model;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import com.mkyong.adapter.JaxbBigDecimalAdapter;
import com.mkyong.adapter.JaxbDateAdapter;
@XmlRootElement(name = "record")
public class Report {
private int refId;
private String name;
private int age;
private Date dob;
private BigDecimal income;
@XmlAttribute(name = "refId")
public int getRefId() {
return refId;
}
public void setRefId(int refId) {
this.refId = refId;
}
@XmlElement(name = "age")
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlJavaTypeAdapter(JaxbDateAdapter.class)
@XmlElement
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
@XmlJavaTypeAdapter(JaxbBigDecimalAdapter.class)
@XmlElement
public BigDecimal getIncome() {
return income;
}
public void setIncome(BigDecimal income) {
this.income = income;
}
//for csv file only
public String getCsvDob() {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
return dateFormat.format(getDob());
}
}
JAXB2では、
Date`や
BigDecimal`のような複雑なデータ型は、注釈がついていてもフィールドに自動的にはマッピングされません。
JAXB2が
Date`変換をサポートするようにするには、
Date format`を手動で処理するカスタムアダプタを作成し、 `@ XmlJavaTypeAdapter`を介してアダプタをアタッチする必要があります。
JaxbDateAdapter.java
package com.mkyong.adapter;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class JaxbDateAdapter extends XmlAdapter<String, Date> {
private SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
@Override
public String marshal(Date date) throws Exception {
return dateFormat.format(date);
}
@Override
public Date unmarshal(String date) throws Exception {
return dateFormat.parse(date);
}
}
`BigDecimal`と同じ、コンマ”、 “XMLの収入要素が変換の問題を引き起こしているので、それを扱うカスタムアダプタも必要です。
JaxbBigDecimalAdapter.java
package com.mkyong.adapter;
import java.math.BigDecimal;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class JaxbBigDecimalAdapter extends XmlAdapter<String, BigDecimal> {
@Override
public String marshal(BigDecimal obj) throws Exception {
return obj.toString();
}
@Override
public BigDecimal unmarshal(String obj) throws Exception {
return new BigDecimal(obj.replaceAll(",", ""));
}
}
6.バネバッチコア設定
jobRepository`と
jobLauncher`を定義してください。
resources/spring/batch/config/context.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">
<!-- stored job-meta in memory -->
<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>
7.バッチバッチジョブ
Springバッチジョブで
report.xml`ファイルを読み込み、
Report`オブジェクトにマップし、csvファイルに書き込みます。コメントを読んで、それは自明であるべきです。
resources/spring/batch/jobs/job-report.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="reportJob">
<batch:step id="step1">
<batch:tasklet>
<batch:chunk reader="xmlItemReader"
writer="cvsFileItemWriter" processor="filterReportProcessor"
commit-interval="1">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
<!-- Filtering process -->
<bean id="filterReportProcessor" class="com.mkyong.processor.FilterReportProcessor"/>
<bean id="xmlItemReader"
class="org.springframework.batch.item.xml.StaxEventItemReader">
<property name="fragmentRootElementName" value="record"/>
<property name="resource" value="classpath:xml/report.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.mkyong.model.Report</value>
</list>
</property>
</bean>
<bean id="cvsFileItemWriter" class="org.springframework.batch.item.file.FlatFileItemWriter">
<!-- write to this csv file -->
<property name="resource" value="file:cvs/report.csv"/>
<property name="shouldDeleteIfExists" value="true"/>
<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="refId, name, age, csvDob, income"/>
</bean>
</property>
</bean>
</property>
</bean>
</beans>
8. Springバッチ – ItemProcessor
Springバッチでは、有線の
Processor`がリソースに書き込む前に起動されるので、これは変換、フィルタリング、ビジネスロジックを処理するのに最適な場所です。この例では、 `
age`が30の場合、 `Report`オブジェクトは無視されます(csvファイルへの書き込みではありません)。
FilterReportProcessor.java
package com.mkyong.processor;
import org.springframework.batch.item.ItemProcessor;
import com.mkyong.model.Report;
//run before writing
public class FilterReportProcessor implements ItemProcessor<Report, Report> {
@Override
public Report process(Report item) throws Exception {
//filter object which age = 30
if(item.getAge()==30){
return null;//null = ignore this object
}
return item;
}
}
9.それを実行する
バッチジョブを実行する最も簡単な方法。
App.java
package com.mkyong;
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;
public class App {
public static void main(String[]args) {
String[]springConfig =
{
"spring/batch/config/context.xml",
"spring/batch/jobs/job-report.xml"
};
ApplicationContext context =
new ClassPathXmlApplicationContext(springConfig);
JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
Job job = (Job) context.getBean("reportJob");
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値はcsvファイルに挿入されます。
csv/report.csv
1001,mkyong,31,31/08/1982,200000 1003,joel,29,21/08/1984,1000000 1004,leeyy,29,21/03/1984,80000.89

ソースコードをダウンロードする
ダウンロードする –
SpringBatch-XML-CSV-Example.zip
(81 kb)
参考文献
バッチItemReadersとItemWriters]。
http://loianegroner.com/2011/06/jaxb-custom-binding-java-util-date-spring-3-serialization/
[JAXB
カスタムバインディング – Java.util.Date]。
http://forum.springsource.org/showthread.php?63282-How-to-use-FlatFileItemWriter
[How
FlatFileItemWriterを使う?]]。
http://static.springsource.org/spring-batch/apidocs/org/springframework/batch/item/file/FlatFileItemWriter.html
[FlatFileItemWriter
JavaDoc]