644 lines
55 KiB
HTML
644 lines
55 KiB
HTML
<html><head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
|
<title>13. Spring Batch Integration</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="index.html" title="Spring Batch - Reference Documentation"><link rel="up" href="index.html" title="Spring Batch - Reference Documentation"><link rel="prev" href="jsr-352.html" title="12. JSR-352 Support"><link rel="next" href="listOfReadersAndWriters.html" title="Appendix A. List of ItemReaders and ItemWriters"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">13. Spring Batch Integration</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="jsr-352.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="listOfReadersAndWriters.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="springBatchIntegration" href="#springBatchIntegration"></a>13. Spring Batch Integration</h1></div></div></div><div class="sect1"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="spring-batch-integration-introduction" href="#spring-batch-integration-introduction"></a>13.1. Spring Batch Integration Introduction</h2></div></div></div><p>
|
|
Many users of Spring Batch may encounter requirements that are
|
|
outside the scope of Spring Batch, yet may be efficiently and
|
|
concisely implemented using Spring Integration. Conversely, Spring
|
|
Batch users may encounter Spring Batch requirements and need a way
|
|
to efficiently integrate both frameworks. In this context several
|
|
patterns and use-cases emerge and Spring Batch Integration will
|
|
address those requirements.
|
|
</p><p>
|
|
The line between Spring Batch and Spring Integration is not always
|
|
clear, but there are guidelines that one can follow. Principally,
|
|
these are: think about granularity, and apply common patterns. Some
|
|
of those common patterns are described in this reference manual
|
|
section.
|
|
</p><p>
|
|
Adding messaging to a batch process enables automation of
|
|
operations, and also separation and strategizing of key concerns.
|
|
For example a message might trigger a job to execute, and then the
|
|
sending of the message can be exposed in a variety of ways. Or when
|
|
a job completes or fails that might trigger a message to be sent,
|
|
and the consumers of those messages might have operational concerns
|
|
that have nothing to do with the application itself. Messaging can
|
|
also be embedded in a job, for example reading or writing items for
|
|
processing via channels. Remote partitioning and remote chunking
|
|
provide methods to distribute workloads over an number of workers.
|
|
</p><p>
|
|
Some key concepts that we will cover are:
|
|
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
|
|
<a class="link" href="springBatchIntegration.html#namespace-support" title="13.1.1. Namespace Support">Namespace Support</a>
|
|
</p></li><li class="listitem"><p>
|
|
<a class="link" href="springBatchIntegration.html#launching-batch-jobs-through-messages" title="13.1.2. Launching Batch Jobs through Messages">Launching
|
|
Batch Jobs through Messages</a>
|
|
</p></li><li class="listitem"><p>
|
|
<a class="link" href="springBatchIntegration.html#providing-feedback-with-informational-messages" title="13.1.3. Providing Feedback with Informational Messages">Providing
|
|
Feedback with Informational Messages</a>
|
|
</p></li><li class="listitem"><p>
|
|
<a class="link" href="springBatchIntegration.html#asynchronous-processors" title="13.1.4. Asynchronous Processors">Asynchronous
|
|
Processors</a>
|
|
</p></li><li class="listitem"><p>
|
|
<a class="link" href="springBatchIntegration.html#externalizing-batch-process-execution" title="13.1.5. Externalizing Batch Process Execution">Externalizing
|
|
Batch Process Execution</a>
|
|
</p></li></ul></div><div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a name="namespace-support" href="#namespace-support"></a>13.1.1. Namespace Support</h3></div></div></div><p>
|
|
Since Spring Batch Integration 1.3, dedicated XML Namespace
|
|
support was added, with the aim to provide an easier configuration
|
|
experience. In order to activate the namespace, add the following
|
|
namespace declarations to your Spring XML Application Context
|
|
file:
|
|
</p><pre class="programlisting"><span class="hl-tag"><beans</span> <span class="hl-attribute">xmlns</span>=<span class="hl-value">"http://www.springframework.org/schema/beans"</span>
|
|
<span class="hl-attribute">xmlns:xsi</span>=<span class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
|
|
<span class="hl-attribute">xmlns:batch-int</span>=<span class="hl-value">"http://www.springframework.org/schema/batch-integration"</span>
|
|
<span class="hl-attribute">xsi:schemaLocation</span>=<span class="hl-value">"
|
|
http://www.springframework.org/schema/batch-integration
|
|
http://www.springframework.org/schema/batch-integration/spring-batch-integration.xsd"</span><span class="hl-tag">></span>
|
|
|
|
...
|
|
|
|
<span class="hl-tag"></beans></span></pre><p>
|
|
A fully configured Spring XML Application Context file for Spring
|
|
Batch Integration may look like the following:
|
|
</p><pre class="programlisting"><span class="hl-tag"><beans</span> <span class="hl-attribute">xmlns</span>=<span class="hl-value">"http://www.springframework.org/schema/beans"</span>
|
|
<span class="hl-attribute">xmlns:xsi</span>=<span class="hl-value">"http://www.w3.org/2001/XMLSchema-instance"</span>
|
|
<span class="hl-attribute">xmlns:int</span>=<span class="hl-value">"http://www.springframework.org/schema/integration"</span>
|
|
<span class="hl-attribute">xmlns:batch</span>=<span class="hl-value">"http://www.springframework.org/schema/batch"</span>
|
|
<span class="hl-attribute">xmlns:batch-int</span>=<span class="hl-value">"http://www.springframework.org/schema/batch-integration"</span>
|
|
<span class="hl-attribute">xsi:schemaLocation</span>=<span class="hl-value">"
|
|
http://www.springframework.org/schema/batch-integration
|
|
http://www.springframework.org/schema/batch-integration/spring-batch-integration.xsd
|
|
http://www.springframework.org/schema/batch
|
|
http://www.springframework.org/schema/batch/spring-batch.xsd
|
|
http://www.springframework.org/schema/beans
|
|
http://www.springframework.org/schema/beans/spring-beans.xsd
|
|
http://www.springframework.org/schema/integration
|
|
http://www.springframework.org/schema/integration/spring-integration.xsd"</span><span class="hl-tag">></span>
|
|
|
|
...
|
|
|
|
<span class="hl-tag"></beans></span></pre><p>
|
|
Appending version numbers to the referenced XSD file is also
|
|
allowed but, as a version-less declaration will always use the
|
|
latest schema, we generally don't recommend appending the version
|
|
number to the XSD name. Adding a version number, for instance,
|
|
would create possibly issues when updating the Spring Batch
|
|
Integration dependencies as they may require more recent versions
|
|
of the XML schema.
|
|
</p></div><div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a name="launching-batch-jobs-through-messages" href="#launching-batch-jobs-through-messages"></a>13.1.2. Launching Batch Jobs through Messages</h3></div></div></div><p>
|
|
When starting batch jobs using the core Spring Batch API you
|
|
basically have 2 options:
|
|
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
|
|
Command line via the <code class="classname">CommandLineJobRunner</code>
|
|
</p></li><li class="listitem"><p>
|
|
Programatically via either
|
|
<code class="classname">JobOperator.start()</code> or
|
|
<code class="classname">JobLauncher.run()</code>.
|
|
</p></li></ul></div><p>
|
|
For example, you may want to use the
|
|
<code class="classname">CommandLineJobRunner</code> when invoking Batch Jobs
|
|
using a shell script. Alternatively, you may use the
|
|
<code class="classname">JobOperator</code> directly, for example when using
|
|
Spring Batch as part of a web application. However, what about
|
|
more complex use-cases? Maybe you need to poll a remote (S)FTP
|
|
server to retrieve the data for the Batch Job. Or your application
|
|
has to support multiple different data sources simultaneously. For
|
|
example, you may receive data files not only via the web, but also
|
|
FTP etc. Maybe additional transformation of the input files is
|
|
needed before invoking Spring Batch.
|
|
</p><p>
|
|
Therefore, it would be much more powerful to execute the batch job
|
|
using Spring Integration and its numerous adapters. For example,
|
|
you can use a <span class="emphasis"><em>File Inbound Channel Adapter</em></span> to
|
|
monitor a directory in the file-system and start the Batch Job as
|
|
soon as the input file arrives. Additionally you can create Spring
|
|
Integration flows that use multiple different adapters to easily
|
|
ingest data for your Batch Jobs from multiple sources
|
|
simultaneously using configuration only. Implementing all these
|
|
scenarios with Spring Integration is easy as it allow for an
|
|
decoupled event-driven execution of the
|
|
<code class="classname">JobLauncher</code>.
|
|
</p><p>
|
|
Spring Batch Integration provides the
|
|
<code class="classname">JobLaunchingMessageHandler</code> class that you can
|
|
use to launch batch jobs. The input for the
|
|
<code class="classname">JobLaunchingMessageHandler</code> is provided by a
|
|
Spring Integration message, which payload is of type
|
|
<code class="classname">JobLaunchRequest</code>. This class is a wrapper around the Job
|
|
that needs to be launched as well as the <code class="classname">JobParameters</code>
|
|
necessary to launch the Batch job.
|
|
</p><p>
|
|
The following image illustrates the typical Spring Integration
|
|
message flow in order to start a Batch job. The
|
|
<a class="ulink" href="http://www.eaipatterns.com/toc.html" target="_top">EIP (Enterprise IntegrationPatterns) website</a>
|
|
provides a full overview of messaging icons and their descriptions.
|
|
</p><div class="mediaobject" align="center"><img src="images/launch-batch-job.png" align="middle"></div><div class="sect3"><div class="titlepage"><div><div><h4 class="title"><a name="transforming-a-file-into-a-joblaunchrequest" href="#transforming-a-file-into-a-joblaunchrequest"></a>Transforming a file into a JobLaunchRequest</h4></div></div></div><pre class="programlisting"><span class="hl-keyword">package</span> io.spring.sbi;
|
|
|
|
<span class="hl-keyword">import</span> org.springframework.batch.core.Job;
|
|
<span class="hl-keyword">import</span> org.springframework.batch.core.JobParametersBuilder;
|
|
<span class="hl-keyword">import</span> org.springframework.batch.integration.launch.JobLaunchRequest;
|
|
<span class="hl-keyword">import</span> org.springframework.integration.annotation.Transformer;
|
|
<span class="hl-keyword">import</span> org.springframework.messaging.Message;
|
|
|
|
<span class="hl-keyword">import</span> java.io.File;
|
|
|
|
<span class="hl-keyword">public</span> <span class="hl-keyword">class</span> FileMessageToJobRequest {
|
|
<span class="hl-keyword">private</span> Job job;
|
|
<span class="hl-keyword">private</span> String fileParameterName;
|
|
|
|
<span class="hl-keyword">public</span> <span class="hl-keyword">void</span> setFileParameterName(String fileParameterName) {
|
|
<span class="hl-keyword">this</span>.fileParameterName = fileParameterName;
|
|
}
|
|
|
|
<span class="hl-keyword">public</span> <span class="hl-keyword">void</span> setJob(Job job) {
|
|
<span class="hl-keyword">this</span>.job = job;
|
|
}
|
|
|
|
<em><span class="hl-annotation" style="color: gray">@Transformer</span></em>
|
|
<span class="hl-keyword">public</span> JobLaunchRequest toRequest(Message<File> message) {
|
|
JobParametersBuilder jobParametersBuilder =
|
|
<span class="hl-keyword">new</span> JobParametersBuilder();
|
|
|
|
jobParametersBuilder.addString(fileParameterName,
|
|
message.getPayload().getAbsolutePath());
|
|
|
|
<span class="hl-keyword">return</span> <span class="hl-keyword">new</span> JobLaunchRequest(job, jobParametersBuilder.toJobParameters());
|
|
}
|
|
}</pre></div><div class="sect3"><div class="titlepage"><div><div><h4 class="title"><a name="the-jobexecution-response" href="#the-jobexecution-response"></a>The JobExecution Response</h4></div></div></div><p>
|
|
When a Batch Job is being executed, a
|
|
<code class="classname">JobExecution</code> instance is returned. This
|
|
instance can be used to determine the status of an execution. If
|
|
a <code class="classname">JobExecution</code> was able to be created
|
|
successfully, it will always be returned, regardless of whether
|
|
or not the actual execution was successful.
|
|
</p><p>
|
|
The exact behavior on how the <code class="classname">JobExecution</code>
|
|
instance is returned depends on the provided
|
|
<code class="classname">TaskExecutor</code>. If a
|
|
<code class="classname">synchronous</code> (single-threaded)
|
|
<code class="classname">TaskExecutor</code> implementation is used, the
|
|
<code class="classname">JobExecution</code> response is only returned
|
|
<code class="classname">after</code> the job completes. When using an
|
|
<code class="classname">asynchronous</code>
|
|
<code class="classname">TaskExecutor</code>, the
|
|
<code class="classname">JobExecution</code> instance is returned
|
|
immediately. Users can then take the <code class="classname">id</code> of
|
|
<code class="classname">JobExecution</code> instance
|
|
(<code class="classname">JobExecution.getJobId()</code>) and query the
|
|
<code class="classname">JobRepository</code> for the job's updated status
|
|
using the <code class="classname">JobExplorer</code>. For more
|
|
information, please refer to the <code class="classname">Spring
|
|
Batch</code> reference documentation on
|
|
<a class="ulink" href="http://docs.spring.io/spring-batch/reference/html/configureJob.html#queryingRepository" target="_top">Querying
|
|
the Repository</a>.
|
|
</p><p>
|
|
The following configuration will create a file
|
|
<code class="classname">inbound-channel-adapter</code> to listen for CSV
|
|
files in the provided directory, hand them off to our
|
|
transformer (<code class="classname">FileMessageToJobRequest</code>),
|
|
launch the job via the <span class="emphasis"><em>Job Launching
|
|
Gateway</em></span> then simply log the output of the
|
|
<code class="classname">JobExecution</code> via the
|
|
<code class="classname">logging-channel-adapter</code>.
|
|
</p></div><div class="sect3"><div class="titlepage"><div><div><h4 class="title"><a name="spring-batch-integration-configuration" href="#spring-batch-integration-configuration"></a>Spring Batch Integration Configuration</h4></div></div></div><pre class="programlisting"><span class="hl-tag"><int:channel</span> <span class="hl-attribute">id</span>=<span class="hl-value">"inboundFileChannel"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"><int:channel</span> <span class="hl-attribute">id</span>=<span class="hl-value">"outboundJobRequestChannel"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"><int:channel</span> <span class="hl-attribute">id</span>=<span class="hl-value">"jobLaunchReplyChannel"</span><span class="hl-tag">/></span>
|
|
|
|
<span class="hl-tag"><int-file:inbound-channel-adapter</span> <span class="hl-attribute">id</span>=<span class="hl-value">"filePoller"</span>
|
|
<span class="hl-attribute">channel</span>=<span class="hl-value">"inboundFileChannel"</span>
|
|
<span class="hl-attribute">directory</span>=<span class="hl-value">"file:/tmp/myfiles/"</span>
|
|
<span class="hl-attribute">filename-pattern</span>=<span class="hl-value">"*.csv"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><int:poller</span> <span class="hl-attribute">fixed-rate</span>=<span class="hl-value">"1000"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></int-file:inbound-channel-adapter></span>
|
|
|
|
<span class="hl-tag"><int:transformer</span> <span class="hl-attribute">input-channel</span>=<span class="hl-value">"inboundFileChannel"</span>
|
|
<span class="hl-attribute">output-channel</span>=<span class="hl-value">"outboundJobRequestChannel"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"io.spring.sbi.FileMessageToJobRequest"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"job"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"personJob"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"fileParameterName"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"input.file.name"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></bean></span>
|
|
<span class="hl-tag"></int:transformer></span>
|
|
|
|
<span class="hl-tag"><batch-int:job-launching-gateway</span> <span class="hl-attribute">request-channel</span>=<span class="hl-value">"outboundJobRequestChannel"</span>
|
|
<span class="hl-attribute">reply-channel</span>=<span class="hl-value">"jobLaunchReplyChannel"</span><span class="hl-tag">/></span>
|
|
|
|
<span class="hl-tag"><int:logging-channel-adapter</span> <span class="hl-attribute">channel</span>=<span class="hl-value">"jobLaunchReplyChannel"</span><span class="hl-tag">/></span></pre><p>
|
|
Now that we are polling for files and launching jobs, we need to
|
|
configure for example our Spring Batch
|
|
<code class="classname">ItemReader</code> to utilize found file
|
|
represented by the job parameter "input.file.name":
|
|
</p></div><div class="sect3"><div class="titlepage"><div><div><h4 class="title"><a name="example-itemreader-configuration" href="#example-itemreader-configuration"></a>Example ItemReader Configuration</h4></div></div></div><pre class="programlisting"><span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"itemReader"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.batch.item.file.FlatFileItemReader"</span>
|
|
<span class="hl-attribute">scope</span>=<span class="hl-value">"step"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"resource"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"file://#{jobParameters['input.file.name']}"</span><span class="hl-tag">/></span>
|
|
...
|
|
<span class="hl-tag"></bean></span></pre><p>
|
|
The main points of interest here are injecting the value of
|
|
<code class="classname">#{jobParameters['input.file.name']}</code>
|
|
as the Resource property value and setting the ItemReader bean
|
|
to be of <span class="emphasis"><em>Step scope</em></span> to take advantage of
|
|
the late binding support which allows access to the
|
|
<code class="classname">jobParameters</code> variable.
|
|
</p><div class="sect4"><div class="titlepage"><div><div><h5 class="title"><a name="available-attributes-of-the-job-launching-gateway" href="#available-attributes-of-the-job-launching-gateway"></a>Available Attributes of the Job-Launching Gateway</h5></div></div></div><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
|
|
<code class="classname">id</code> Identifies the
|
|
underlying Spring bean definition, which is an instance of
|
|
either:
|
|
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
|
|
<code class="classname">EventDrivenConsumer</code>
|
|
</p></li><li class="listitem"><p>
|
|
<code class="classname">PollingConsumer</code>
|
|
</p></li></ul></div><p>
|
|
The exact implementation depends on whether the component's
|
|
input channel is a:
|
|
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem"><p>
|
|
<code class="classname">SubscribableChannel</code> or
|
|
</p></li><li class="listitem"><p>
|
|
<code class="classname">PollableChannel</code>
|
|
</p></li></ul></div></li></ul></div><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
|
|
<code class="classname">auto-startup</code>
|
|
Boolean flag to indicate that the endpoint should start automatically on
|
|
startup. The default is <span class="emphasis"><em>true</em></span>.
|
|
</p></li><li class="listitem"><p>
|
|
<code class="classname">request-channel</code>
|
|
The input <code class="classname">MessageChannel</code> of this endpoint.
|
|
</p></li><li class="listitem"><p>
|
|
<code class="classname">reply-channel</code> <code class="classname">Message Channel</code>
|
|
to which the resulting <code class="classname">JobExecution</code> payload will be sent.
|
|
</p></li><li class="listitem"><p>
|
|
<code class="classname">reply-timeout</code>
|
|
Allows you to specify how long this gateway will wait for the reply message
|
|
to be sent successfully to the reply channel before throwing
|
|
an exception. This attribute only applies when the channel
|
|
might block, for example when using a bounded queue channel
|
|
that is currently full. Also, keep in mind that when sending to a
|
|
<code class="classname">DirectChannel</code>, the invocation will occur
|
|
in the sender's thread. Therefore, the failing of the send
|
|
operation may be caused by other components further downstream.
|
|
The <code class="classname">reply-timeout</code> attribute maps to the
|
|
<code class="classname">sendTimeout</code> property of the underlying
|
|
<code class="classname">MessagingTemplate</code> instance. The attribute
|
|
will default, if not specified, to<span class="emphasis"><em>-1</em></span>,
|
|
meaning that by default, the Gateway will wait indefinitely.
|
|
The value is specified in milliseconds.
|
|
</p></li><li class="listitem"><p>
|
|
<code class="classname">job-launcher</code>
|
|
Pass in a
|
|
custom
|
|
<code class="classname">JobLauncher</code>
|
|
bean reference. This
|
|
attribute is optional. If not specified the adapter will
|
|
re-use the instance that is registered under the id
|
|
<code class="classname">jobLauncher</code>. If no default instance
|
|
exists an exception is thrown.
|
|
</p></li><li class="listitem"><p>
|
|
<code class="classname">order</code>
|
|
Specifies the order
|
|
for invocation when this endpoint is connected as a subscriber
|
|
to a <code class="classname">SubscribableChannel</code>.
|
|
</p></li></ul></div></div><div class="sect4"><div class="titlepage"><div><div><h5 class="title"><a name="sub-elements" href="#sub-elements"></a>Sub-Elements</h5></div></div></div><p>
|
|
When this Gateway is receiving messages from a
|
|
<code class="classname">PollableChannel</code>, you must either provide
|
|
a global default Poller or provide a Poller sub-element to the
|
|
<code class="classname">Job Launching Gateway</code>:
|
|
</p><pre class="programlisting"><span class="hl-tag"><batch-int:job-launching-gateway</span> <span class="hl-attribute">request-channel</span>=<span class="hl-value">"queueChannel"</span>
|
|
<span class="hl-attribute">reply-channel</span>=<span class="hl-value">"replyChannel"</span> <span class="hl-attribute">job-launcher</span>=<span class="hl-value">"jobLauncher"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><int:poller</span> <span class="hl-attribute">fixed-rate</span>=<span class="hl-value">"1000"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></batch-int:job-launching-gateway></span></pre></div></div></div><div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a name="providing-feedback-with-informational-messages" href="#providing-feedback-with-informational-messages"></a>13.1.3. Providing Feedback with Informational Messages</h3></div></div></div><p>
|
|
As Spring Batch jobs can run for long times, providing progress
|
|
information will be critical. For example, stake-holders may want
|
|
to be notified if a some or all parts of a Batch Job has failed.
|
|
Spring Batch provides support for this information being gathered
|
|
through:
|
|
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
|
|
Active polling or
|
|
</p></li><li class="listitem"><p>
|
|
Event-driven, using listeners.
|
|
</p></li></ul></div><p>
|
|
When starting a Spring Batch job asynchronously, e.g. by using the
|
|
<code class="classname">Job Launching Gateway</code>, a
|
|
<code class="classname">JobExecution</code> instance is returned. Thus,
|
|
<code class="classname">JobExecution.getJobId()</code> can be used to
|
|
continuously poll for status updates by retrieving updated
|
|
instances of the <code class="classname">JobExecution</code> from the
|
|
<code class="classname">JobRepository</code> using the
|
|
<code class="classname">JobExplorer</code>. However, this is considered
|
|
sub-optimal and an event-driven approach should be preferred.
|
|
</p><p>
|
|
Therefore, Spring Batch provides listeners such as:
|
|
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
|
|
StepListener
|
|
</p></li><li class="listitem"><p>
|
|
ChunkListener
|
|
</p></li><li class="listitem"><p>
|
|
JobExecutionListener
|
|
</p></li></ul></div><p>
|
|
In the following example, a Spring Batch job was configured with a
|
|
<code class="classname">StepExecutionListener</code>. Thus, Spring
|
|
Integration will receive and process any step before/after step
|
|
events. For example, the received
|
|
<code class="classname">StepExecution</code> can be inspected using a
|
|
<code class="classname">Router</code>. Based on the results of that
|
|
inspection, various things can occur for example routing a message
|
|
to a Mail Outbound Channel Adapter, so that an Email notification
|
|
can be sent out based on some condition.
|
|
</p><div class="mediaobject" align="center"><img src="images/handling-informational-messages.png" align="middle"></div><p>
|
|
Below is an example of how a listener is configured to send a
|
|
message to a <code class="classname">Gateway</code> for
|
|
<code class="classname">StepExecution</code> events and log its output to a
|
|
<code class="classname">logging-channel-adapter</code>:
|
|
</p><p>
|
|
First create the notifications integration beans:
|
|
</p><pre class="programlisting"><span class="hl-tag"><int:channel</span> <span class="hl-attribute">id</span>=<span class="hl-value">"stepExecutionsChannel"</span><span class="hl-tag">/></span>
|
|
|
|
<span class="hl-tag"><int:gateway</span> <span class="hl-attribute">id</span>=<span class="hl-value">"notificationExecutionsListener"</span>
|
|
<span class="hl-attribute">service-interface</span>=<span class="hl-value">"org.springframework.batch.core.StepExecutionListener"</span>
|
|
<span class="hl-attribute">default-request-channel</span>=<span class="hl-value">"stepExecutionsChannel"</span><span class="hl-tag">/></span>
|
|
|
|
<span class="hl-tag"><int:logging-channel-adapter</span> <span class="hl-attribute">channel</span>=<span class="hl-value">"stepExecutionsChannel"</span><span class="hl-tag">/></span></pre><p>
|
|
Then modify your job to add a step level listener:
|
|
</p><pre class="programlisting"><span class="hl-tag"><job</span> <span class="hl-attribute">id</span>=<span class="hl-value">"importPayments"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><step</span> <span class="hl-attribute">id</span>=<span class="hl-value">"step1"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><tasklet</span> <span class="hl-attribute">../></span>
|
|
<span class="hl-attribute"><chunk</span> <span class="hl-attribute">../></span>
|
|
<span class="hl-attribute"><listeners></span>
|
|
<span class="hl-attribute"><listener</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"notificationExecutionsListener"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></listeners></span>
|
|
<span class="hl-tag"></tasklet></span>
|
|
...
|
|
<span class="hl-tag"></step></span>
|
|
<span class="hl-tag"></job></span></pre></div><div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a name="asynchronous-processors" href="#asynchronous-processors"></a>13.1.4. Asynchronous Processors</h3></div></div></div><p>
|
|
Asynchronous Processors help you to to scale the processing of
|
|
items. In the asynchronous processor use-case, an
|
|
<code class="classname">AsyncItemProcessor</code> serves as a dispatcher,
|
|
executing the <code class="classname">ItemProcessor</code>'s logic for an
|
|
item on a new thread. The <code class="classname">Future</code> is passed to
|
|
the <code class="classname">AsynchItemWriter</code> to be written once the
|
|
processor completes.
|
|
</p><p>
|
|
Therefore, you can increase performance by using asynchronous item
|
|
processing, basically allowing you to implement
|
|
<span class="emphasis"><em>fork-join</em></span> scenarios. The
|
|
<code class="classname">AsyncItemWriter</code> will gather the results and
|
|
write back the chunk as soon as all the results become available.
|
|
</p><p>
|
|
Configuration of both the <code class="classname">AsyncItemProcessor</code>
|
|
and <code class="classname">AsyncItemWriter</code> are simple, first the
|
|
<code class="classname">AsyncItemProcessor</code>:
|
|
</p><pre class="programlisting"><span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"processor"</span>
|
|
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.batch.integration.async.AsyncItemProcessor"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"delegate"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"your.ItemProcessor"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></property></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"taskExecutor"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.core.task.SimpleAsyncTaskExecutor"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></property></span>
|
|
<span class="hl-tag"></bean></span></pre><p>
|
|
The property "<code class="classname">delegate</code>" is actually
|
|
a reference to your <code class="classname">ItemProcessor</code> bean and
|
|
the "<code class="classname">taskExecutor</code>" property is a
|
|
reference to the <code class="classname">TaskExecutor</code> of your choice.
|
|
</p><p>
|
|
Then we configure the <code class="classname">AsyncItemWriter</code>:
|
|
</p><pre class="programlisting"><span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"itemWriter"</span>
|
|
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.batch.integration.async.AsyncItemWriter"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"delegate"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"itemWriter"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"your.ItemWriter"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></property></span>
|
|
<span class="hl-tag"></bean></span></pre><p>
|
|
Again, the property "<code class="classname">delegate</code>" is
|
|
actually a reference to your <code class="classname">ItemWriter</code> bean.
|
|
</p></div><div class="sect2"><div class="titlepage"><div><div><h3 class="title"><a name="externalizing-batch-process-execution" href="#externalizing-batch-process-execution"></a>13.1.5. Externalizing Batch Process Execution</h3></div></div></div><p>
|
|
The integration approaches discussed so far suggest use-cases
|
|
where Spring Integration wraps Spring Batch like an outer-shell.
|
|
However, Spring Batch can also use Spring Integration internally.
|
|
Using this approach, Spring Batch users can delegate the
|
|
processing of items or even chunks to outside processes. This
|
|
allows you to offload complex processing. Spring Batch Integration
|
|
provides dedicated support for:
|
|
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
|
|
Remote Chunking
|
|
</p></li><li class="listitem"><p>
|
|
Remote Partitioning
|
|
</p></li></ul></div><div class="sect3"><div class="titlepage"><div><div><h4 class="title"><a name="remote-chunking" href="#remote-chunking"></a>Remote Chunking</h4></div></div></div><div class="mediaobject" align="center"><img src="images/remote-chunking-sbi.png" align="middle"></div><p>
|
|
Taking things one step further, one can also externalize the
|
|
chunk processing using the
|
|
<code class="classname">ChunkMessageChannelItemWriter</code> which is
|
|
provided by Spring Batch Integration which will send items out
|
|
and collect the result. Once sent, Spring Batch will continue the
|
|
process of reading and grouping items, without waiting for the results.
|
|
Rather it is the responsibility of the <code class="classname">ChunkMessageChannelItemWriter</code>
|
|
to gather the results and integrate them back into the Spring Batch process.
|
|
</p><p>
|
|
Using Spring Integration you have full
|
|
control over the concurrency of your processes, for instance by
|
|
using a <code class="classname">QueueChannel</code> instead of a
|
|
<code class="classname">DirectChannel</code>. Furthermore, by relying on
|
|
Spring Integration's rich collection of Channel Adapters (E.g.
|
|
JMS or AMQP), you can distribute chunks of a Batch job to
|
|
external systems for processing.
|
|
</p><p>
|
|
A simple job with a step to be remotely chunked would have a
|
|
configuration similar to the following:
|
|
</p><pre class="programlisting"><span class="hl-tag"><job</span> <span class="hl-attribute">id</span>=<span class="hl-value">"personJob"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><step</span> <span class="hl-attribute">id</span>=<span class="hl-value">"step1"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><tasklet></span>
|
|
<span class="hl-tag"><chunk</span> <span class="hl-attribute">reader</span>=<span class="hl-value">"itemReader"</span> <span class="hl-attribute">writer</span>=<span class="hl-value">"itemWriter"</span> <span class="hl-attribute">commit-interval</span>=<span class="hl-value">"200"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></tasklet></span>
|
|
...
|
|
<span class="hl-tag"></step></span>
|
|
<span class="hl-tag"></job></span></pre><p>
|
|
The ItemReader reference would point to the bean you would like
|
|
to use for reading data on the master. The ItemWriter reference
|
|
points to a special ItemWriter
|
|
"<code class="classname">ChunkMessageChannelItemWriter</code>"
|
|
as described above. The processor (if any) is left off the
|
|
master configuration as it is configured on the slave. The
|
|
following configuration provides a basic master setup. It's
|
|
advised to check any additional component properties such as
|
|
throttle limits and so on when implementing your use case.
|
|
</p><pre class="programlisting"><span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"connectionFactory"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.apache.activemq.ActiveMQConnectionFactory"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"brokerURL"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"tcp://localhost:61616"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></bean></span>
|
|
|
|
<span class="hl-tag"><int-jms:outbound-channel-adapter</span> <span class="hl-attribute">id</span>=<span class="hl-value">"requests"</span> <span class="hl-attribute">destination-name</span>=<span class="hl-value">"requests"</span><span class="hl-tag">/></span>
|
|
|
|
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"messagingTemplate"</span>
|
|
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.integration.core.MessagingTemplate"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"defaultChannel"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"requests"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"receiveTimeout"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"2000"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></bean></span>
|
|
|
|
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"itemWriter"</span>
|
|
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.batch.integration.chunk.ChunkMessageChannelItemWriter"</span>
|
|
<span class="hl-attribute">scope</span>=<span class="hl-value">"step"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"messagingOperations"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"messagingTemplate"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"replyChannel"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"replies"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></bean></span>
|
|
|
|
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"chunkHandler"</span>
|
|
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.batch.integration.chunk.RemoteChunkHandlerFactoryBean"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"chunkWriter"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"itemWriter"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"step"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"step1"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></bean></span>
|
|
|
|
<span class="hl-tag"><int:channel</span> <span class="hl-attribute">id</span>=<span class="hl-value">"replies"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><int:queue/></span>
|
|
<span class="hl-tag"></int:channel></span>
|
|
|
|
<span class="hl-tag"><int-jms:message-driven-channel-adapter</span> <span class="hl-attribute">id</span>=<span class="hl-value">"jmsReplies"</span>
|
|
<span class="hl-attribute">destination-name</span>=<span class="hl-value">"replies"</span>
|
|
<span class="hl-attribute">channel</span>=<span class="hl-value">"replies"</span><span class="hl-tag">/></span></pre><p>
|
|
This configuration provides us with a number of beans. We
|
|
configure our messaging middleware using ActiveMQ and
|
|
inbound/outbound JMS adapters provided by Spring Integration. As
|
|
shown, our <code class="classname">itemWriter</code> bean which is
|
|
referenced by our job step utilizes the
|
|
<code class="classname">ChunkMessageChannelItemWriter</code> for writing chunks over the
|
|
configured middleware.
|
|
</p><p>
|
|
Now lets move on to the slave configuration:
|
|
</p><pre class="programlisting"><span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"connectionFactory"</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.apache.activemq.ActiveMQConnectionFactory"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"brokerURL"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"tcp://localhost:61616"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></bean></span>
|
|
|
|
<span class="hl-tag"><int:channel</span> <span class="hl-attribute">id</span>=<span class="hl-value">"requests"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"><int:channel</span> <span class="hl-attribute">id</span>=<span class="hl-value">"replies"</span><span class="hl-tag">/></span>
|
|
|
|
<span class="hl-tag"><int-jms:message-driven-channel-adapter</span> <span class="hl-attribute">id</span>=<span class="hl-value">"jmsIn"</span>
|
|
<span class="hl-attribute">destination-name</span>=<span class="hl-value">"requests"</span>
|
|
<span class="hl-attribute">channel</span>=<span class="hl-value">"requests"</span><span class="hl-tag">/></span>
|
|
|
|
<span class="hl-tag"><int-jms:outbound-channel-adapter</span> <span class="hl-attribute">id</span>=<span class="hl-value">"outgoingReplies"</span>
|
|
<span class="hl-attribute">destination-name</span>=<span class="hl-value">"replies"</span>
|
|
<span class="hl-attribute">channel</span>=<span class="hl-value">"replies"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"></int-jms:outbound-channel-adapter></span>
|
|
|
|
<span class="hl-tag"><int:service-activator</span> <span class="hl-attribute">id</span>=<span class="hl-value">"serviceActivator"</span>
|
|
<span class="hl-attribute">input-channel</span>=<span class="hl-value">"requests"</span>
|
|
<span class="hl-attribute">output-channel</span>=<span class="hl-value">"replies"</span>
|
|
<span class="hl-attribute">ref</span>=<span class="hl-value">"chunkProcessorChunkHandler"</span>
|
|
<span class="hl-attribute">method</span>=<span class="hl-value">"handleChunk"</span><span class="hl-tag">/></span>
|
|
|
|
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"chunkProcessorChunkHandler"</span>
|
|
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.batch.integration.chunk.ChunkProcessorChunkHandler"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"chunkProcessor"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.batch.core.step.item.SimpleChunkProcessor"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"itemWriter"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"io.spring.sbi.PersonItemWriter"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></property></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"itemProcessor"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"io.spring.sbi.PersonItemProcessor"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></property></span>
|
|
<span class="hl-tag"></bean></span>
|
|
<span class="hl-tag"></property></span>
|
|
<span class="hl-tag"></bean></span></pre><p>
|
|
Most of these configuration items should look familiar from the
|
|
master configuration. Slaves do not need access to things like
|
|
the Spring Batch <code class="classname">JobRepository</code> nor access
|
|
to the actual job configuration file. The main bean of interest
|
|
is the
|
|
"<code class="classname">chunkProcessorChunkHandler</code>". The
|
|
<code class="classname">chunkProcessor</code> property of
|
|
<code class="classname">ChunkProcessorChunkHandler</code> takes a
|
|
configured <code class="classname">SimpleChunkProcessor</code> which is
|
|
where you would provide a reference to your
|
|
<code class="classname">ItemWriter</code> and optionally your
|
|
<code class="classname">ItemProcessor</code> that will run on the slave
|
|
when it receives chunks from the master.
|
|
</p><p>
|
|
For more information, please also consult the Spring Batch
|
|
manual, specifically the chapter on
|
|
<a class="ulink" href="http://docs.spring.io/spring-batch/reference/html/scalability.html#remoteChunking" target="_top">Remote
|
|
Chunking</a>.
|
|
</p></div><div class="sect3"><div class="titlepage"><div><div><h4 class="title"><a name="remote-partitioning" href="#remote-partitioning"></a>Remote Partitioning</h4></div></div></div><div class="mediaobject" align="center"><img src="images/remote-partitioning.png" align="middle"></div><p>
|
|
Remote Partitioning, on the other hand, is useful when the
|
|
problem is not the processing of items, but the associated I/O
|
|
represents the bottleneck. Using Remote Partitioning, work can
|
|
be farmed out to slaves that execute complete Spring Batch
|
|
steps. Thus, each slave has its own
|
|
<code class="classname">ItemReader</code>,
|
|
<code class="classname">ItemProcessor</code> and
|
|
<code class="classname">ItemWriter</code>. For this purpose, Spring Batch
|
|
Integration provides the
|
|
<code class="classname">MessageChannelPartitionHandler</code>.
|
|
</p><p>
|
|
This implementation of the <code class="classname">PartitionHandler</code>
|
|
interface uses <code class="classname">MessageChannel</code> instances to
|
|
send instructions to remote workers and receive their responses.
|
|
This provides a nice abstraction from the transports (E.g. JMS
|
|
or AMQP) being used to communicate with the remote workers.
|
|
</p><p>
|
|
The reference manual section
|
|
<a class="ulink" href="http://docs.spring.io/spring-batch/reference/html/scalability.html#partitioning" target="_top">Remote
|
|
Partitioning</a> provides an overview of the concepts and
|
|
components needed to configure Remote Partitioning and shows an
|
|
example of using the default
|
|
<code class="classname">TaskExecutorPartitionHandler</code> to partition
|
|
in separate local threads of execution. For Remote Partitioning
|
|
to multiple JVM's, two additional components are required:
|
|
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>
|
|
Remoting fabric or grid environment
|
|
</p></li><li class="listitem"><p>
|
|
A PartitionHandler implementation that supports the desired
|
|
remoting fabric or grid environment
|
|
</p></li></ul></div><p>
|
|
Similar to Remote Chunking JMS can be used as the "remoting
|
|
fabric" and the PartitionHandler implementation to be used
|
|
as described above is the
|
|
<code class="classname">MessageChannelPartitionHandler</code>. The example
|
|
shown below assumes an existing partitioned job and focuses on
|
|
the <code class="classname">MessageChannelPartitionHandler</code> and JMS
|
|
configuration:
|
|
</p><pre class="programlisting"><span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"partitionHandler"</span>
|
|
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.batch.integration.partition.MessageChannelPartitionHandler"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"stepName"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"step1"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"gridSize"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"3"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"replyChannel"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"outbound-replies"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"messagingOperations"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><bean</span> <span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.integration.core.MessagingTemplate"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"defaultChannel"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"outbound-requests"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"receiveTimeout"</span> <span class="hl-attribute">value</span>=<span class="hl-value">"100000"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></bean></span>
|
|
<span class="hl-tag"></property></span>
|
|
<span class="hl-tag"></bean></span>
|
|
|
|
<span class="hl-tag"><int:channel</span> <span class="hl-attribute">id</span>=<span class="hl-value">"outbound-requests"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"><int-jms:outbound-channel-adapter</span> <span class="hl-attribute">destination</span>=<span class="hl-value">"requestsQueue"</span>
|
|
<span class="hl-attribute">channel</span>=<span class="hl-value">"outbound-requests"</span><span class="hl-tag">/></span>
|
|
|
|
<span class="hl-tag"><int:channel</span> <span class="hl-attribute">id</span>=<span class="hl-value">"inbound-requests"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"><int-jms:message-driven-channel-adapter</span> <span class="hl-attribute">destination</span>=<span class="hl-value">"requestsQueue"</span>
|
|
<span class="hl-attribute">channel</span>=<span class="hl-value">"inbound-requests"</span><span class="hl-tag">/></span>
|
|
|
|
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"stepExecutionRequestHandler"</span>
|
|
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.batch.integration.partition.StepExecutionRequestHandler"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"jobExplorer"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"jobExplorer"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"><property</span> <span class="hl-attribute">name</span>=<span class="hl-value">"stepLocator"</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"stepLocator"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"></bean></span>
|
|
|
|
<span class="hl-tag"><int:service-activator</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"stepExecutionRequestHandler"</span> <span class="hl-attribute">input-channel</span>=<span class="hl-value">"inbound-requests"</span>
|
|
<span class="hl-attribute">output-channel</span>=<span class="hl-value">"outbound-staging"</span><span class="hl-tag">/></span>
|
|
|
|
<span class="hl-tag"><int:channel</span> <span class="hl-attribute">id</span>=<span class="hl-value">"outbound-staging"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"><int-jms:outbound-channel-adapter</span> <span class="hl-attribute">destination</span>=<span class="hl-value">"stagingQueue"</span>
|
|
<span class="hl-attribute">channel</span>=<span class="hl-value">"outbound-staging"</span><span class="hl-tag">/></span>
|
|
|
|
<span class="hl-tag"><int:channel</span> <span class="hl-attribute">id</span>=<span class="hl-value">"inbound-staging"</span><span class="hl-tag">/></span>
|
|
<span class="hl-tag"><int-jms:message-driven-channel-adapter</span> <span class="hl-attribute">destination</span>=<span class="hl-value">"stagingQueue"</span>
|
|
<span class="hl-attribute">channel</span>=<span class="hl-value">"inbound-staging"</span><span class="hl-tag">/></span>
|
|
|
|
<span class="hl-tag"><int:aggregator</span> <span class="hl-attribute">ref</span>=<span class="hl-value">"partitionHandler"</span> <span class="hl-attribute">input-channel</span>=<span class="hl-value">"inbound-staging"</span>
|
|
<span class="hl-attribute">output-channel</span>=<span class="hl-value">"outbound-replies"</span><span class="hl-tag">/></span>
|
|
|
|
<span class="hl-tag"><int:channel</span> <span class="hl-attribute">id</span>=<span class="hl-value">"outbound-replies"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><int:queue/></span>
|
|
<span class="hl-tag"></int:channel></span>
|
|
|
|
<span class="hl-tag"><bean</span> <span class="hl-attribute">id</span>=<span class="hl-value">"stepLocator"</span>
|
|
<span class="hl-attribute">class</span>=<span class="hl-value">"org.springframework.batch.integration.partition.BeanFactoryStepLocator"</span><span class="hl-tag"> /></span></pre><p>
|
|
Also ensure the partition <code class="classname">handler</code> attribute
|
|
maps to the <code class="classname">partitionHandler</code> bean:
|
|
</p><pre class="programlisting"><span class="hl-tag"><job</span> <span class="hl-attribute">id</span>=<span class="hl-value">"personJob"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><step</span> <span class="hl-attribute">id</span>=<span class="hl-value">"step1.master"</span><span class="hl-tag">></span>
|
|
<span class="hl-tag"><partition</span> <span class="hl-attribute">partitioner</span>=<span class="hl-value">"partitioner"</span> <span class="hl-attribute">handler</span>=<span class="hl-value">"partitionHandler"</span><span class="hl-tag">/></span>
|
|
...
|
|
<span class="hl-tag"></step></span>
|
|
<span class="hl-tag"></job></span></pre></div></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="jsr-352.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="listOfReadersAndWriters.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">12. JSR-352 Support </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Appendix A. List of ItemReaders and ItemWriters</td></tr></table></div></body></html> |