春のバッチの例 – 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]