Application_Developer_Guide

batterycopperInternet and Web Development

Nov 12, 2013 (3 years and 9 months ago)

78 views

Spring
-
Batch Tutorial

Guide for Application
Developers

Agenda


“Hello world!” job


Simple job


programming a Tasklet
directly


Common job


weaving standard
components


Sample jobs


“Hello World!”
-

tasklet

public

class

HelloWorldTasklet
implements

Tasklet {


public

ExitStatus execute()
throws

Exception {



System.
out
.println(
"Hello world!"
);




return

ExitStatus.
FINISHED
;


}

}

“Hello World!”
-

tasklet

public

class

HelloWorldTasklet
implements

Tasklet {


public

ExitStatus execute()
throws

Exception {



System.
out
.println(
"Hello world!"
);




return

ExitStatus.
FINISHED
;


}

}

“Hello World!”
-

configuration

<
bean
id
=
"jobConfiguration"
parent
=
"simpleJob"
>


<
property
name
=
"name"
value
=
"helloWorldJob"
/>


<
property
name
=
"steps"
>



<
list
>



<
bean
id
=
"step1"
parent
=
"simpleStep"
>




<
constructor
-
arg
>




<
bean
class
=
"...HelloWorldTasklet"
/>




</
constructor
-
arg
>



</
bean
>



</
list
>


</
property
>

</
bean
>

“Hello World!”
-

configuration

<
bean
id
=
"jobConfiguration"
parent
=
"simpleJob"
>


<
property
name
=
"name"
value
=
"helloWorldJob"
/>


<
property
name
=
"steps"
>



<
list
>



<
bean
id
=
"step1"
parent
=
"simpleStep"
>




<
constructor
-
arg
>




<
bean
class
=
"...HelloWorldTasklet"
/>




</
constructor
-
arg
>



</
bean
>



</
list
>


</
property
>

</
bean
>

Simple job
-

tasklet

public

class

SimpleTasklet
implements

Tasklet {



private

InputSource
inputSource
;


private

OutputSource
outputSource
;




public

ExitStatus execute()
throws

Exception {



Object data =
inputSource
.read();






if

(data !=
null
) {




outputSource
.write(data);




return

ExitStatus.
CONTINUABLE
;



}



return

ExitStatus.
FINISHED
;


}


public

void

setInputSource(InputSource inputSource) {



this
.
inputSource

= inputSource;


}


public

void

setOutputSource(OutputSource outputSource) {



this
.
outputSource

= outputSource;


}

}

Simple job
-

tasklet

public

class

SimpleTasklet
implements

Tasklet {



private

InputSource
inputSource
;


private

OutputSource
outputSource
;




public

ExitStatus execute()
throws

Exception {



Object data =
inputSource
.read();






if

(data !=
null
) {




outputSource
.write(data);




return

ExitStatus.
CONTINUABLE
;



}



return

ExitStatus.
FINISHED
;


}


public

void

setInputSource(InputSource inputSource) {



this
.
inputSource

= inputSource;


}


public

void

setOutputSource(OutputSource outputSource) {



this
.
outputSource

= outputSource;


}

}

Simple job
-

tasklet

public

class

SimpleTasklet
implements

Tasklet {



private

InputSource
inputSource
;


private

OutputSource
outputSource
;




public

ExitStatus execute()
throws

Exception {



Object data =
inputSource
.read();






if

(data !=
null
) {




outputSource
.write(data);




return

ExitStatus.
CONTINUABLE
;



}



return

ExitStatus.
FINISHED
;


}


public

void

setInputSource(InputSource inputSource) {



this
.
inputSource

= inputSource;


}


public

void

setOutputSource(OutputSource outputSource) {



this
.
outputSource

= outputSource;


}

}

Simple job
-

configuration

<
bean
id
=
"jobConfiguration"
parent
=
"simpleJob"
>


<
property
name
=
"name"
value
=
"simpleTaskletJob"
/>


<
property
name
=
"steps"
>



<
list
>



<
bean
id
=
"step1"
parent
=
"simpleStep"
>



<
constructor
-
arg
>




<
bean
class
=
"...SimpleTasklet"
>




<
property
name
=
"inputSource"
ref
=
"inputSource"
/>




<
property
name
=
"outputSource"
ref
=
"outputSource"
/>




</
bean
>



</
constructor
-
arg
>



</
bean
>



</
list
>


</
property
>

</
bean
>

Simple job


input source

<
bean
id
=
“inputSource"

class
=
"...SqlCursorInputSource“
scope
=
"step"
>


<
aop:scoped
-
proxy /
>


<
property
name
=
"dataSource"
ref
=
"dataSource" /
>


<
property
name
=
"sql"



value
=
"SELECT id, quantity, price, customer from TRADE"
/>


<
property
name
=
"mapper"
>



<
bean
class
=
"...TradeRowMapper"
/>


</
property
>

</
bean
>

Simple job


input source

<
bean
id
=
“inputSource"

class
=
"...SqlCursorInputSource“
scope
=
"step"
>


<
aop:scoped
-
proxy /
>


<
constructor
-
arg
>


<
ref
bean
=
"dataSource"
/>



</
constructor
-
arg
>


<
property
name
=
"sql"



value
=
"SELECT id, quantity, price, customer from TRADE"
/>


<
property
name
=
"mapper"
>



<
bean
class
=
"...TradeRowMapper"
/>


</
property
>

</
bean
>

Simple job


output source

<
bean
id
=
"outputSource"
class
=
"...FlatFileOutputSource“



scope
=
"step"
>


<aop:scoped
-
proxy />


<
property
name
=
"resource"
value
=
"file:out.txt" /
>

</
bean
>

Common job
-

configuration

<
bean
id
=
"jobConfiguration"
parent
=
"simpleJob"
>


<
property
name
=
"name"
value
=
"commonJob"
/>


<
property
name
=
"steps"
>



<
bean
id
=
"step1"
parent
=
"simpleStep"
>



<
constructor
-
arg
>






<
bean

class
=
"...tasklet.RestartableItemProviderTasklet"
>




<
property
name
=
"itemProvider"
>




<
bean

class
=
"...tasklet.support.InputSourceItemProvider"
>




<
property
name
=
"source"
ref
=
"sqlInputSource"
/>




</
bean
>




</
property
>




<
property
name
=
"itemProcessor"
>




<
bean
class
=
"...tasklet.support.OutputSourceItemProcessor"
>




<
property
name
=
"source"
ref
=
"xmlOutputSource"
/>




</
bean
>




</
property
>




</
bean
>



</
constructor
-
arg
>



</
bean
>


</
property
>

</
bean
>

Common job


tasklet

<
bean

class
=
"...tasklet.RestartableItemProviderTasklet"
>




<
property
name
=
"itemProvider"
>



<
bean

class
=
"...tasklet.support.InputSourceItemProvider"
>



<
property
name
=
"source"
ref
=
"sqlInputSource"
/>



</
bean
>


</
property
>



<
property
name
=
"itemProcessor"
>



<
bean
class
=
"...tasklet.support.OutputSourceItemProcessor"
>



<
property
name
=
"source"
ref
=
"xmlOutputSource"
/>



</
bean
>


</
property
>


</
bean
>

Common job


tasklet

<
bean

class
=
"...tasklet.RestartableItemProviderTasklet"
>




<
property
name
=
"itemProvider"
>



<
bean

class
=
"...tasklet.support.InputSourceItemProvider"
>



<
property
name
=
"source"
ref
=
"sqlInputSource"
/>



</
bean
>


</
property
>



<
property
name
=
"itemProcessor"
>



<
bean
class
=
"...tasklet.support.OutputSourceItemProcessor"
>



<
property
name
=
"source"
ref
=
"xmlOutputSource"
/>



</
bean
>


</
property
>


</
bean
>

Common job


tasklet

<
bean

class
=
"...tasklet.RestartableItemProviderTasklet"
>




<
property
name
=
"itemProvider"
>



<
bean

class
=
"...tasklet.support.InputSourceItemProvider"
>



<
property
name
=
"source"
ref
=
"sqlInputSource"
/>



</
bean
>


</
property
>



<
property
name
=
"itemProcessor"
>



<
bean
class
=
"...tasklet.support.OutputSourceItemProcessor"
>



<
property
name
=
"source"
ref
=
"xmlOutputSource"
/>



</
bean
>


</
property
>


</
bean
>

Samples overview


Samples project contains simple batch
jobs illustrating various capabilities of the
Spring
-
Batch framework


See the folder
src/main/resources/jobs

for
job configuration files


See
src/test/java
, package
org.springframework.batch.sample

for
tests which launch the jobs and check the
expected results


simpleTaskletJob.xml


Straightforwardly implemented Tasklet,
similar to the “Simple Job” example


All
-
in
-
one solution to help understand
tasklet’s execution logic


Standard solutions are more modular,
which makes them more flexible and
reusable, but also less straightforward to
understand

fixedLengthImportJob.xml


Clean separation of reading input and
processing data (standard from now on)


Typical scenario of importing data from a
fixed
-
length file to database


Custom DAO used for output

multilineOrderJob.xml


Handling of complex file format, both
reading input and writing output


Single record spans multiple lines and has
nested records


Custom ItemProvider and ItemProcessor
implementations handling non
-
standard
file format


tradeJob.xml


shows a reasonably complex scenario,
that would resemble the real
-
life usage
of the framework


3 steps:


trade records are imported from file to
database


customer account balance is adjusted


report about customers is exported to a file






compositeProcessorSample.xml


Parallel writing to multiple outputs


Example usage of composite
ItemProcessor with an injected list of
ItemProcessors

restartSample.xml


Simulates restart scenario, where the job
crashes on first run and succeeds after
being restarted


Uses ‘hacked’ tasklet that throws
exception after reading a given number of
records