Spring Batch-Beispiel - XML-Datei in die MongoDB-Datenbank

Beispiel für einen Frühlingsstapel - XML-Datei in MongoDB-Datenbank

In diesem Tutorial zeigen wir Ihnen, wie Sie einen Spring Batch-Job so konfigurieren, dass Daten aus einer XML-Datei (XStream Bibliothek) in eine No-SQL-Datenbank (MongoDB) gelesen werden. Erstellen Sie außerdem einen Komponententestfall, um die Stapeljobs zu starten und zu testen.

Verwendete Tools und Bibliotheken

  1. Maven 3

  2. Eclipse 4.2

  3. JDK 1.6

  4. Federkern 3.2.2.FREIGABE

  5. Spring Batch 2.2.0.RELEASE

  6. Federbatch-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. Einfaches Java-Projekt

1. Erstellen Sie ein Java-Schnellstartprojekt mit Maven, konvertieren Sie es und importieren Sie es in die Eclipse-IDE.

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

2. Projektabhängigkeiten

Deklariert alle Projektabhängigkeiten inpom.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. Projektverzeichnisstruktur

Überprüfen Sie die endgültige Projektstruktur und verschaffen Sie sich einen Überblick über die nächsten Schritte.

spring batch - xml to mongodb

4. XML-Datei

Dies ist die XML-Datei im Ressourcenordner.

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-Datei lesen

Im Spring Batch können wirStaxEventItemReader zum Lesen von XML-Dateien undXStreamMarshaller zum Zuordnen von XML-Werten und -Attributen zu einem Objekt verwenden.

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

}

Um den XML-Wert einem „komplexen“ Datentyp wieDate undBigDecimal zuzuordnen, müssen Sie ein benutzerdefiniertesconverter anhängen, um den Wert manuell zu konvertieren und zuzuordnen.

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-Datenbank

Definieren Sie eine Mongodb-Instanz sowiemongoTemplate.

resources/spring/batch/config/database.xml



        
    
    

    
        
    

7. Federbatch-Kerneinstellung

Definieren SiejobRepository undjobLauncher.

resources/spring/batch/config/context.xml



    
    
    
    

    


    
    
    

8. Spring Batch-Jobs

Ein Spring-Batch-Job, lesen Sie die Dateireport.xml, ordnen Sie sie einem ObjektReportzu und schreiben Sie sie inMongoDB. Lesen Sie den Kommentar, er sollte selbsterklärend sein.

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



    
    
      
        
        
      
    
    

    
    
    
    
    
    

    
    
    
      
        
      
    

        
    
      
        
      
    

    

    

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

9. Gerätetest

Unit-Test mit jUnit- oder TestNG-Frameworks. Zunächst müssen Sie dieJobLauncherTestUtils manuell deklarieren.

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



    
    

Ein Beispiel

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 Beispiel

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);

    }
}

Ausgabe. Die XML-Werte werden in die MongoDB eingefügt.

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. Wie wäre es mit den Job-Metadaten?

Entschuldigung, ich habe noch keine Lösung dafür. Wie ich weiß, wird die relationale Datenbank für Job-Metadaten benötigt, um die Neustartfähigkeit und das Rollback der Jobs sicherzustellen. Die MongoDB hat kein "solides" Transaktionsmanagement.

Lösung 1: Erstellen Sie eine andere relationale Datenbank, um die Job-Metadaten zu speichern, hmm ... Das klingt dumm, funktioniert aber. Hast du bessere Ideen?

Lösung 2: Warten Sie, bis das Spring-Team eine Lösung für dieses Problem gefunden hat.

Quellcode herunterladen

Laden Sie es herunter -SpringBatch-XML-MongoDB-Example.zip (81 kb)