Spring Batch 2. díl

V předchozím díle jsme se věnovali představení frameworku String Batch, vysvětlení základních pojmů a ukázali jsme si jednoduchý projekt. V tomto díle vytvoříme další projekt.

Job je posloupnost jednotlivých kroků (Step). Krok pak obsahuje úkol (Tasklet), který popisuje (implementuje) co se má dělat. Task v sobě ještě může obsahovat další kousek (Chunk), ale tomu se budemě věnovat někdy příště.

Vaříme čaj se Spring Batch.
V následujícím příkladu si ukážeme job, který se bude skládat s pěti kroků (Tasklet). Budeme připravovat čaj.

  1. naplníme konvici vodou
  2. zapneme konvici
  3. dáme do konvice čaj
  4. počkáme tři minuty
  5. hotový čaj naservírujeme

Struktura projektu

│   pom.xml
│
└───src
    ├───main
    │   └───java
    │       └───cz
    │           └───vitfo
    │               │   ExecuteJob.java
    │               │
    │               └───tasklets
    │                       FillKettleWithWater.java
    │                       PutTeaToWater.java
    │                       ServeTea.java
    │                       TurnOnKettle.java
    │                       WaitThreeMinutes.java
    │
    └───resources
            context.xml
            job.xml


Všimněte si, že ve složce resources máme dva xml. Spring umožňuje rozdělit konfiguraci do více souborů. Jednou z možností je potom pro vytvoření kontextu předat list konfiguračních souboru (ukázáno v tomto příspěvku) a nebo importovat jeden konfigurační soubor do druhého pomocí elementu <import> jak je ukázáno v tomto příkladu (řádek osm v souboru job.xml).

context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/batch"
	xmlns:beans="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.0.xsd 
						http://www.springframework.org/schema/batch 
						http://www.springframework.org/schema/batch/spring-batch-3.0.xsd">
	
	<beans:bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
		<beans:property name="transactionManager" ref="transactionManager" />
	</beans:bean>
	
	<beans:bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
		<beans:property name="jobRepository" ref="jobRepository" />
	</beans:bean>
	
	<beans:bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
</beans:beans>

V tomto souboru jsou definice bean jobRepository, jobLauncher a transactionManager.

job.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/batch"
	xmlns:beans="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.0.xsd
						http://www.springframework.org/schema/batch
						http://www.springframework.org/schema/batch/spring-batch-3.0.xsd">
	<beans:import resource="context.xml" />
	
	<!-- Beans definition -->		
	<beans:bean id="fillKettleWithWater" class="cz.vitfo.tasklets.FillKettleWithWater"/>
	<beans:bean id="turnOnKettle" class="cz.vitfo.tasklets.TurnOnKettle"/>
	<beans:bean id="putTeaToWater" class="cz.vitfo.tasklets.PutTeaToWater"/>
	<beans:bean id="waitThreeMinutes" class="cz.vitfo.tasklets.WaitThreeMinutes"/>
	<beans:bean id="serveTea" class="cz.vitfo.tasklets.ServeTea"/>
	
	<!-- Job definition -->
	<job id="prepareTeaJob">
		<step id="fillKetleWitWaterStep" next="turnOnKettleStep">
			<tasklet ref="fillKettleWithWater"/>
		</step>
		<step id="turnOnKettleStep" next="putTeaToWaterStep">
			<tasklet ref="turnOnKettle"/>
		</step>
		<step id="putTeaToWaterStep" next="waitThreeMinutesStep">
			<tasklet ref="putTeaToWater"/>
		</step>
		<step id="waitThreeMinutesStep" next="serveTeaStep">
			<tasklet ref="waitThreeMinutes"/>
		</step>
		<step id="serveTeaStep">
			<tasklet ref="serveTea"/>
		</step>
	</job>
</beans:beans>

Zde definujeme job, jeho jednotlivé kroky a v nich úkoly. Třída představující tasklet musí implementovat rozhraní Tasklet a logiku definovat v metodě execute(). Celkem budeme používat pět taskletů.

FillKettleWithWater.java

import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;

public class FillKettleWithWater implements Tasklet {

	public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
		System.out.println("Filling kettle with the water.");
		return null;
	}
}

TurnOnKettle.java

import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;

public class TurnOnKettle implements Tasklet {

	public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
		System.out.println("Turning the kettle on.");
		return null;
	}
}

PutTeaToWater.java

import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;

public class PutTeaToWater implements Tasklet {

	public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
		System.out.println("Putting delicious tea to the hot water.");
		return null;
	}
}

WaitThreeMinutes.java

import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;

public class WaitThreeMinutes implements Tasklet {

	public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
		System.out.println("Waiting for three minutes to infuse tea.");
		return null;
	}
}

ServeTea.java

import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;

public class ServeTea implements Tasklet {

	public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
		System.out.println("Serving the tea.");
		return null;
	}
}

Všechny tasklety jsou jednoduché a jediné co dělají je, že do konzole vytisknou text.

Nakonec nám zbývá třída s metodou main, ve které vytvoříme kontext, pomocí JobLancher spustíme job a zobrazíme JobExecution status.

ExecuteJob.java

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 ExecuteJob {

	public static void main(String[] args) {
		String[] springConfig = {"job.xml"};
		ApplicationContext context = new ClassPathXmlApplicationContext(springConfig);
		
		JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
		Job job = (Job) context.getBean("prepareTeaJob");
		
		try {
			JobExecution execution = jobLauncher.run(job, new JobParameters());
			System.out.println("Exit Status: " + execution.getStatus());
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (context != null) {
				context = null;
			}
		}
		System.out.println("Done");
	}
}

Výsledek spuštění.

Filling kettle with the water.
Turning the kettle on.
Putting delicious tea to the hot water.
Waiting for three minutes to infuse tea.
Serving the tea.
Exit Status: COMPLETED
Done

Napsat komentář