Пример Spring Batch - XML-файл в базу данных MongoDB

Пример Spring Batch - XML-файл в базу данных MongoDB

В этом руководстве мы покажем вам, как настроить задание Spring Batch для чтения данных из файла XML (библиотекаXStream) в базу данных без SQL (MongoDB). Кроме того, создайте тестовый блок для запуска и тестирования пакетных заданий.

Использованные инструменты и библиотеки

  1. Maven 3

  2. Затмение 4.2

  3. JDK 1.6

  4. Spring Core 3.2.2.RELEASE

  5. Spring Batch 2.2.0.RELEASE

  6. Spring Batch Test 2.2.0.RELEASE

  7. Spring OXM 3.2.2.RELEASE

  8. MongoDB Java Driver 2.11.2

  9. MongoDB 2.2.3

  10. JUnit 4.11

  11. TestNG 6.8.5

P.S This example – XML file (reader) – MongoDB (writer).

1. Простой Java-проект

1. Создать быстрый старт Java Project с Maven, конвертировать и импортировать в Eclipse IDE.

$ mvn archetype:generate -DgroupId=com.example -DartifactId=SpringBatchExample2
  -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
$ cd SpringBatchExample/
$ mvn eclipse:eclipse

2. Зависимости проекта

Объявляет все зависимости проекта вpom.xml

pom.xml


    4.0.0
    com.example
    SpringBatchExample
    jar
    1.0-SNAPSHOT
    SpringBatchExample
    http://maven.apache.org

    
        1.6
        3.2.2.RELEASE
        2.2.0.RELEASE
        1.2.1.RELEASE
        2.11.2
    

    

        
        
            org.springframework
            spring-core
            ${spring.version}
        

        
        
            org.springframework
            spring-oxm
            ${spring.version}
        

        
        
            org.springframework.batch
            spring-batch-core
            ${spring.batch.version}
        
        
            org.springframework.batch
            spring-batch-infrastructure
            ${spring.batch.version}
        

        
        
            org.springframework.batch
            spring-batch-test
            ${spring.batch.version}
        

        
        
            org.mongodb
            mongo-java-driver
            ${mongodb.driver.version}
        

        
        
            org.springframework.data
            spring-data-mongodb
            ${spring.data.version}
        

        
        
            junit
            junit
            4.11
            test
        

        
        
            org.testng
            testng
            6.8.5
            test
        

    
    
        spring-batch
        
        
            org.apache.maven.plugins
            maven-eclipse-plugin
            2.9
            
                true
                false
            
        
        
            org.apache.maven.plugins
            maven-compiler-plugin
            2.3.2
            
                ${jdk.version}
                ${jdk.version}
            
        
        
    

3. Структура каталога проекта

Просмотрите окончательную структуру проекта, получите представление о том, что будет дальше.

spring batch - xml to mongodb

4. XML-файл

Это файл XML в папке ресурсов.

resources/xml/report.xml



    
        6/1/2013
        139,237
        40
        220.90
    
    
        6/2/2013
        339,100
        60
        320.88
    
    
        6/3/2013
        431,436
        76
        270.80
    

5. Читать XML-файл

В пакете Spring мы можем использоватьStaxEventItemReader для чтения файлов XML иXStreamMarshaller для сопоставления значений и атрибутов XML с объектом.

resources/spring/batch/jobs/job-report.xml

    
    
    
    
    
    

    

    
        
        
        
    
    
        
        
        
    

    

    

Report.java

package com.example.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.example.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.example.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



        
    
    

    
        
    

7. Настройка основной партии пружин

ОпределитеjobRepository иjobLauncher.

resources/spring/batch/config/context.xml



    
    
    
    

    


    
    
    

8. Весенние партии рабочих мест

Пакетное задание Spring: прочтите файлreport.xml, сопоставьте его с объектомReport и запишите его вMongoDB. Прочитайте комментарий, он должен быть понятен.

resources/spring/batch/jobs/job-report.xml



    
    
      
        
        
      
    
    

    
    
    
    
    
    

    
    
    
      
        
      
    

        
    
      
        
      
    

    

    

    //write it to MongoDB, 'report' collection (table)
    
    
    
    

9. Модульный тест

Модульное тестирование с помощью jUnit или TestNG framework. Сначала вы должны объявитьJobLauncherTestUtils вручную.

test/resources/spring/batch/config/test-context.xml



    
    

jUnit пример

AppTest.java

package com.example;

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.example;

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.example.model.Report",
"date" : ISODate("2013-05-31T16:00:00Z"), "impression" : NumberLong(139237),
"clicks" : 40, "earning" : "220.90" }

{ "_id" : 2, "_class" : "com.example.model.Report",
"date" : ISODate("2013-06-01T16:00:00Z"), "impression" : NumberLong(339100),
"clicks" : 60, "earning" : "320.88" }

{ "_id" : 3, "_class" : "com.example.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 кб)