Springバッチの例 – MongoDBデータベースへのXMLファイル
このチュートリアルでは、XMLファイル(
XStream
ライブラリ)のデータをno SQLデータベース(
MongoDB
)に読み込むようにSpringバッチジョブを設定する方法を説明します。さらに、バッチジョブを起動してテストする単体テストケースを作成します。
使用されるツールとライブラリ
-
Maven 3
-
Eclipse 4.2
-
JDK 1.6
-
Spring Core 3.2.2.RELEASE
-
Spring Batch 2.2.0.RELEASE
-
春バッチテスト2.2.0.RELEASE
-
Spring OXM 3.2.2.RELEASE
-
MongoDB Javaドライバ2.11.2
-
MongoDB 2.2.3
-
jUnit 4.11
-
TestNG 6.8.5
P.Sこの例 – XMLファイル(リーダー) – MongoDB(ライター).
1.シンプルなJavaプロジェクト
{空} 1。 MavenでクイックスタートJavaプロジェクトを作成し、変換してEclipse IDEにインポートします。
$ mvn archetype:generate -DgroupId=com.mkyong -DartifactId=SpringBatchExample2 -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
$ cd SpringBatchExample/$ 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>
<spring.data.version>1.2.1.RELEASE</spring.data.version>
<mongodb.driver.version>2.11.2</mongodb.driver.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>
<!-- Spring Batch unit test -->
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<version>${spring.batch.version}</version>
</dependency>
<!-- MongoDB database driver -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>${mongodb.driver.version}</version>
</dependency>
<!-- Spring data mongodb -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>${spring.data.version}</version>
</dependency>
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- Testng -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8.5</version>
<scope>test</scope>
</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ファイル
これは、リソースフォルダ内のXMLファイルです。
resources/xml/report.xml
<?xml version="1.0" encoding="UTF-8" ?>
<report>
<record id="1">
<date>6/1/2013</date>
<impression>139,237</impression>
<clicks>40</clicks>
<earning>220.90</earning>
</record>
<record id="2">
<date>6/2/2013</date>
<impression>339,100</impression>
<clicks>60</clicks>
<earning>320.88</earning>
</record>
<record id="3">
<date>6/3/2013</date>
<impression>431,436</impression>
<clicks>76</clicks>
<earning>270.80</earning>
</record>
</report>
5. XMLファイルを読む
Springバッチでは、
StaxEventItemReader`を使ってXMLファイルを読み込み、
XStreamMarshaller`を使ってXML値と属性をオブジェクトにマップすることができます。
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>
<bean id="reportUnmarshaller"
class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="aliases">
<util:map id="aliases">
<entry key="record" value="com.mkyong.model.Report"/>
</util:map>
</property>
<property name="converters">
<array>
<ref bean="reportConverter"/>
</array>
</property>
</bean>
<bean id="reportConverter" class="com.mkyong.converter.ReportConverter"/>
Report.java
package com.mkyong.model;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Report {
private int id;
private Date date;
private long impression;
private int clicks;
private BigDecimal earning;
//getter and setter methods
}
XML値を
Date`や
BigDecimal`のような複雑なデータ型にマップするには、値を手作業で変換してマップするためにカスタムの `converter`をつける必要があります。
ReportConverter.java
package com.mkyong.converter;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import com.mkyong.model.Report;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
public class ReportConverter implements Converter {
@Override
public boolean canConvert(Class type) {
//we only need "Report" object
return type.equals(Report.class);
}
@Override
public void marshal(Object source,
HierarchicalStreamWriter writer, MarshallingContext context) {
//do nothing
}
@Override
public Object unmarshal(
HierarchicalStreamReader reader, UnmarshallingContext context) {
Report obj = new Report();
//get attribute
obj.setId(Integer.valueOf(reader.getAttribute("id")));
reader.moveDown();//get date
Date date = null;
try {
date = new SimpleDateFormat("M/d/yyyy").parse(reader.getValue());
} catch (ParseException e) {
e.printStackTrace();
}
obj.setDate(date);
reader.moveUp();
reader.moveDown();//get impression
String impression = reader.getValue();
NumberFormat format = NumberFormat.getInstance(Locale.US);
Number number = 0;
try {
number = format.parse(impression);
} catch (ParseException e) {
e.printStackTrace();
}
obj.setImpression(number.longValue());
reader.moveUp();
reader.moveDown();//get click
obj.setClicks(Integer.valueOf(reader.getValue()));
reader.moveUp();
reader.moveDown();//get earning
obj.setEarning(new BigDecimal(reader.getValue()));
reader.moveUp();
return obj;
}
}
6. MongoDBデータベース
mongodbインスタンスと `mongoTemplate ‘を定義します。
resources/spring/batch/config/database.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
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
http://www.springframework.org/schema/data/mongo
http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">
<!-- connect to mongodb -->
<mongo:mongo host="127.0.0.1" port="27017"/>
<mongo:db-factory dbname="yourdb"/>
<bean id="mongoTemplate"
class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
</bean>
</beans>
7.スプリングバッチコア設定
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>
8.バネバッチジョブ
Springバッチジョブで
report.xml`ファイルを読み込み、
Report`オブジェクトにマップし、 `MongoDB`に書き込みます。コメントを読む、それは自明でなければならない。
resources/spring/batch/jobs/job-report.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:batch="http://www.springframework.org/schema/batch"
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="mongodbItemWriter"
commit-interval="1">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
<!-- Read XML file -->
<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>
<!-- Maps XML values to Object -->
<bean id="reportUnmarshaller"
class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="aliases">
<util:map id="aliases">
<entry key="record" value="com.mkyong.model.Report"/>
</util:map>
</property>
<!-- attach a custom converter -->
<property name="converters">
<array>
<ref bean="reportConverter"/>
</array>
</property>
</bean>
<bean id="reportConverter" class="com.mkyong.converter.ReportConverter"/>
//write it to MongoDB, 'report' collection (table)
<bean id="mongodbItemWriter"
class="org.springframework.batch.item.data.MongoItemWriter">
<property name="template" ref="mongoTemplate"/>
<property name="collection" value="report"/>
</bean>
</beans>
9.単体テスト
ユニットはjUnitまたはTestNGフレームワークでテストします。まず、 `JobLauncherTestUtils`を手動で宣言する必要があります。
test/resources/spring/batch/config/test-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">
<!-- this bean should auto load -->
<bean class="org.springframework.batch.test.JobLauncherTestUtils"/>
</beans>
jUnitの例
AppTest.java
package com.mkyong;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath:spring/batch/jobs/job-report.xml",
"classpath:spring/batch/config/context.xml",
"classpath:spring/batch/config/database.xml",
"classpath:spring/batch/config/test-context.xml"})
public class AppTest {
@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
@Test
public void launchJob() throws Exception {
//JobExecution jobExecution = jobLauncherTestUtils.launchJob();
JobExecution jobExecution = jobLauncherTestUtils.launchStep("step1");
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
}
}
TestNGの例
AppTest2.java
package com.mkyong;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.Assert;
import org.testng.annotations.Test;
@ContextConfiguration(locations = {
"classpath:spring/batch/jobs/job-report.xml",
"classpath:spring/batch/config/context.xml",
"classpath:spring/batch/config/database.xml",
"classpath:spring/batch/config/test-context.xml"})
public class AppTest2 extends AbstractTestNGSpringContextTests {
@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
@Test
public void launchJob() throws Exception {
JobExecution jobExecution = jobLauncherTestUtils.launchJob();
Assert.assertEquals(jobExecution.getStatus(), BatchStatus.COMPLETED);
}
}
出力。 XML値はMongoDBに挿入されます。
mongo
MongoDB shell version: 2.2.3
connecting to: test
> use yourdb
switched to db yourdb
> show collections
report
system.indexes
> db.report.find()
{ "__id" : 1, "__class" : "com.mkyong.model.Report",
"date" : ISODate("2013-05-31T16:00:00Z"), "impression" : NumberLong(139237),
"clicks" : 40, "earning" : "220.90" }
{ "__id" : 2, "__class" : "com.mkyong.model.Report",
"date" : ISODate("2013-06-01T16:00:00Z"), "impression" : NumberLong(339100),
"clicks" : 60, "earning" : "320.88" }
{ "__id" : 3, "__class" : "com.mkyong.model.Report",
"date" : ISODate("2013-06-02T16:00:00Z"), "impression" : NumberLong(431436),
"clicks" : 76, "earning" : "270.80" }
>
10.ジョブメタデータはどうですか?
申し訳ありませんが、私はまだこれのための解決策がありません。私が知っているように、ジョブの再始動性とロールバックを保証するために、リレーショナル・データベースがジョブ・メタデータに必要です。 MongoDBには、設計通りに「強固な」トランザクション管理がありません。
解決策1:ジョブメタデータを格納する別のリレーショナルデータベースを作成する、うーん…それは愚かだが動作する。もっと良いアイデアはありますか?
解決策2:Springのチームが解決策を出すのを待ちます。
ソースコードをダウンロードする
ダウンロードする –
SpringBatch-XML-MongoDB-Example.zip
(81 kb)
参考文献
-
http://xstream.codehaus.org/converter-tutorial.html
[XStream converter
チュートリアル]。
http://forum.springsource.org/archive/index.php/t-97452.html
[Spring
非RDBMSのバッチサポート]。
http://static.springsource.org/spring-batch/reference/html/readersAndWriters.html#xmlReadingWriting
[Spring
バッチXMLアイテムリーダーとライター]。
http://static.springsource.org/spring-batch/reference/html/configureJob.html
[Spring
バッチ – ジョブの設定と実行]。 link://maven/how-to-create-a-java-project-with-maven/[Javaを作成する
Mavenのプロジェクト]