Java Reference
In-Depth Information
In the outline for this example
job
, the first
step
had to come before the second two because the
second two are dependent on the first. The second two, however, do not share any such dependencies.
There's no reason why the audit log couldn't be written at the same time as the JMS messages are being
delivered. Spring Batch provides the capability to fork processing to enable just this sort of arrangement:
<job job-repository="jobRepository"
id="insertIntoDbFromCsvJob">
<step id="loadRegistrations" next="finalizeRegistrations"
➥
> <!-- ... --> </step>
<split id="finalizeRegistrations" >
<flow>
<step id="reportStatistics" ><!-- ... --></step>
</flow>
<flow>
<step id="sendJmsNotifications" > <!-- ... --></step>
</flow>
</split>
</job>
In this example, there's nothing to prevent you from having many
step
s within the
flow
elements,
nor was there anything preventing you from having more
step
s after the
split
element. The
split
element, like the
step
elements, takes a
next
attribute as well.
Spring Batch provides a mechanism to offload processing to another process. This feature, called
remote chunking
, is new in Spring Batch 2.0. This distribution requires some sort of durable, reliable
connection. This is a perfect use of JMS because it's rock-solid and transactional, fast, and reliable.
Spring Batch support is modeled at a slightly higher level, on top of the Spring Integration abstractions
for Spring Integration channels. This support is not in the main Spring Batch code, though. Remote
chunking lets individual
step
s read and aggregate items_as usual_in the main thread. This
step
is called
the
Master
. Items read are sent to the
ItemProcessor
/
ItemWriter
running in another process (this is
called the
Slave
). If the
Slave
is an aggressive consumer, you have a simple, generic mechanism to scale:
work is instantly farmed out over as many JMS clients as you can throw at it. The
aggressive-consumer
pattern refers to the arrangement of multiple JMS clients all consuming the same queue's messages. If
one client consumes a message and is busy processing, other idle queues will get the message instead. As
long as there's a client that's idle, the message will be processed instantly.
Additionally, Spring Batch supports implicitly scaling out using a feature called
partitioning
. This
feature is interesting because it's built in and generally very flexible. You replace your instance of a
step
with a subclass,
PartitionStep
, which knows how to coordinate distributed executors and maintains the
metadata for the execution of the
step
, thus eliminating the need for a durable medium of
communication as in the “remote chunking” technology.
The functionality here is also very generic. It could, conceivably, be used with any sort of grid
fabric technology such as GridGain or Hadoop. (For more on GridGain, see Chapter 10.) Spring Batch
ships with only a
TaskExecutorPartitionHandler
, which executes
step
s in multiple threads using a
TaskExecutor
strategy. This simple improvement might be enough of a justification for this feature! If
you're really hurting, however, you can extend it.
Conditional Steps with Statuses
Using the
ExitStatus
of a given
step
to determine the next
step
is the simplest example of a conditional
flow. Spring Batch facilitates this through the use of the
stop
,
next
,
fail
and
end
elements. By default,
assuming no intervention, a
step
will have an
ExitStatus
that matches its
BatchStatus
, which is a
property whose values are defined in an enum and may be any of the following:
COMPLETED
,
COMPLETED
WITH SKIPS
,
STARTING
,
STARTED
,
STOPPING
,
STOPPED
,
FAILED
,
ABANDONED
or
UNKNOWN
.
Search WWH ::
Custom Search