Files
spring-batch/build/reference-epub-work/ch04s05.xhtml
Michael Minella 75ab909314 update
2017-03-23 10:18:33 -05:00

128 lines
12 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xmlns:m="http://www.w3.org/1998/Math/MathML" xmlns:pls="http://www.w3.org/2005/01/pronunciation-lexicon" xmlns:ssml="http://www.w3.org/2001/10/synthesis" xmlns:svg="http://www.w3.org/2000/svg"><head><title>Running a Job</title><link rel="stylesheet" type="text/css" href="docbook-epub.css"/><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"/><link rel="prev" href="ch04s04.xhtml" title="Configuring a JobLauncher"/><link rel="next" href="ch04s06.xhtml" title="Advanced Meta-Data Usage"/></head><body><header/><section class="section" title="Running a Job" epub:type="subchapter" id="runningAJob"><div class="titlepage"><div><div><h2 class="title" style="clear: both">Running a Job</h2></div></div></div><p>At a minimum, launching a batch job requires two things: the
<code class="classname">Job</code> to be launched and a
<code class="classname">JobLauncher</code>. Both can be contained within the same
context or different contexts. For example, if launching a job from the
command line, a new JVM will be instantiated for each Job, and thus every
job will have its own <code class="classname">JobLauncher</code>. However, if
running from within a web container within the scope of an
<code class="classname">HttpRequest</code>, there will usually be one
<code class="classname">JobLauncher</code>, configured for asynchronous job
launching, that multiple requests will invoke to launch their jobs.</p><section class="section" title="Running Jobs from the Command Line" epub:type="division" id="runningJobsFromCommandLine"><div class="titlepage"><div><div><h3 class="title">Running Jobs from the Command Line</h3></div></div></div><p>For users that want to run their jobs from an enterprise
scheduler, the command line is the primary interface. This is because
most schedulers (with the exception of Quartz unless using the
<code class="classname">NativeJob</code>) work directly with operating system
processes, primarily kicked off with shell scripts. There are many ways
to launch a Java process besides a shell script, such as Perl, Ruby, or
even 'build tools' such as ant or maven. However, because most people
are familiar with shell scripts, this example will focus on them.</p><section class="section" title="The CommandLineJobRunner" epub:type="division" id="commandLineJobRunner"><div class="titlepage"><div><div><h4 class="title">The CommandLineJobRunner</h4></div></div></div><p>Because the script launching the job must kick off a Java
Virtual Machine, there needs to be a class with a main method to act
as the primary entry point. Spring Batch provides an implementation
that serves just this purpose:
<code class="classname">CommandLineJobRunner</code>. It's important to note
that this is just one way to bootstrap your application, but there are
many ways to launch a Java process, and this class should in no way be
viewed as definitive. The <code class="classname">CommandLineJobRunner</code>
performs four tasks:</p><div class="itemizedlist" epub:type="list"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem" epub:type="list-item"><p>Load the appropriate
<code class="classname">ApplicationContext</code></p></li><li class="listitem" epub:type="list-item"><p>Parse command line arguments into
<code class="classname">JobParameters</code></p></li><li class="listitem" epub:type="list-item"><p>Locate the appropriate job based on arguments</p></li><li class="listitem" epub:type="list-item"><p>Use the <code class="classname">JobLauncher</code> provided in the
application context to launch the job.</p></li></ul></div><p>All of these tasks are accomplished using only the arguments
passed in. The following are required arguments:</p><div class="table" id="d5e1113"><div class="table-title">Table 4.1. CommandLineJobRunner arguments</div><div class="table-contents"><table style="border-collapse: collapse; border-top: 0.5pt solid ; border-bottom: 0.5pt solid ; border-left: 0.5pt solid ; border-right: 0.5pt solid ; "><colgroup><col/><col/></colgroup><tbody><tr><td style="border-right: 0.5pt solid ; border-bottom: 0.5pt solid ; ">jobPath</td><td style="border-bottom: 0.5pt solid ; ">The location of the XML file that will be used to
create an <code class="classname">ApplicationContext</code>. This file
should contain everything needed to run the complete
<code class="classname">Job</code></td></tr><tr><td style="border-right: 0.5pt solid ; ">jobName</td><td>The name of the job to be run.</td></tr></tbody></table></div></div><p>These arguments must be passed in with the path first and the
name second. All arguments after these are considered to be
JobParameters and must be in the format of 'name=value':</p><pre class="screen"><code class="prompt">bash$</code> java CommandLineJobRunner endOfDayJob.xml endOfDay schedule.date(date)=2007/05/05</pre><p>In most cases you would want to use a manifest to declare your
main class in a jar, but for simplicity, the class was used directly.
This example is using the same 'EndOfDay' example from the <a class="link" href="ch03.xhtml" title="Chapter 3. The Domain Language of Batch">domain section</a>. The first argument is
'endOfDayJob.xml', which is the Spring
<code class="classname">ApplicationContext</code> containing the
<code class="classname">Job</code>. The second argument, 'endOfDay' represents
the job name. The final argument, 'schedule.date(date)=2007/05/05'
will be converted into <code class="classname">JobParameters</code>. An
example of the XML configuration is below:</p><pre class="programlisting">&lt;job id="endOfDay"&gt;
&lt;step id="step1" parent="simpleStep" /&gt;
&lt;/job&gt;
&lt;!-- Launcher details removed for clarity --&gt;
&lt;beans:bean id="jobLauncher"
class="org.springframework.batch.core.launch.support.SimpleJobLauncher" /&gt;</pre><p>This example is overly simplistic, since there are many more
requirements to a run a batch job in Spring Batch in general, but it
serves to show the two main requirements of the
<code class="classname">CommandLineJobRunner</code>:
<code class="classname">Job</code> and
<code class="classname">JobLauncher</code></p></section><section class="section" title="ExitCodes" epub:type="division" id="exitCodes"><div class="titlepage"><div><div><h4 class="title">ExitCodes</h4></div></div></div><p>When launching a batch job from the command-line, an enterprise
scheduler is often used. Most schedulers are fairly dumb and work only
at the process level. This means that they only know about some
operating system process such as a shell script that they're invoking.
In this scenario, the only way to communicate back to the scheduler
about the success or failure of a job is through return codes. A
return code is a number that is returned to a scheduler by the process
that indicates the result of the run. In the simplest case: 0 is
success and 1 is failure. However, there may be more complex
scenarios: If job A returns 4 kick off job B, and if it returns 5 kick
off job C. This type of behavior is configured at the scheduler level,
but it is important that a processing framework such as Spring Batch
provide a way to return a numeric representation of the 'Exit Code'
for a particular batch job. In Spring Batch this is encapsulated
within an <code class="classname">ExitStatus</code>, which is covered in more
detail in Chapter 5. For the purposes of discussing exit codes, the
only important thing to know is that an
<code class="classname">ExitStatus</code> has an exit code property that is
set by the framework (or the developer) and is returned as part of the
<code class="classname">JobExecution</code> returned from the
<code class="classname">JobLauncher</code>. The
<code class="classname">CommandLineJobRunner</code> converts this string value
to a number using the <code class="classname">ExitCodeMapper</code>
interface:</p><pre class="programlisting">public interface ExitCodeMapper {
public int intValue(String exitCode);
}</pre><p>The essential contract of an
<code class="classname">ExitCodeMapper</code> is that, given a string exit
code, a number representation will be returned. The default
implementation used by the job runner is the SimpleJvmExitCodeMapper
that returns 0 for completion, 1 for generic errors, and 2 for any job
runner errors such as not being able to find a
<code class="classname">Job</code> in the provided context. If anything more
complex than the 3 values above is needed, then a custom
implementation of the <code class="classname">ExitCodeMapper</code> interface
must be supplied. Because the
<code class="classname">CommandLineJobRunner</code> is the class that creates
an <code class="classname">ApplicationContext</code>, and thus cannot be
'wired together', any values that need to be overwritten must be
autowired. This means that if an implementation of
<code class="classname">ExitCodeMapper</code> is found within the BeanFactory,
it will be injected into the runner after the context is created. All
that needs to be done to provide your own
<code class="classname">ExitCodeMapper</code> is to declare the implementation
as a root level bean and ensure that it is part of the
<code class="classname">ApplicationContext</code> that is loaded by the
runner.</p></section></section><section class="section" title="Running Jobs from within a Web Container" epub:type="division" id="runningJobsFromWebContainer"><div class="titlepage"><div><div><h3 class="title">Running Jobs from within a Web Container</h3></div></div></div><p>Historically, offline processing such as batch jobs have been
launched from the command-line, as described above. However, there are
many cases where launching from an <code class="classname">HttpRequest</code> is
a better option. Many such use cases include reporting, ad-hoc job
running, and web application support. Because a batch job by definition
is long running, the most important concern is ensuring to launch the
job asynchronously:</p><div style="text-align: center; " class="mediaobject"><img style="text-align: middle; " src="images/launch-from-request.png" width="405"/></div><p>The controller in this case is a Spring MVC controller. More
information on Spring MVC can be found here: <a class="ulink" href="http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html" target="_top">http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html</a>.
The controller launches a <code class="classname">Job</code> using a
<code class="classname">JobLauncher</code> that has been configured to launch
<a class="link" href="">asynchronously</a>, which
immediately returns a <code class="classname">JobExecution</code>. The
<code class="classname">Job</code> will likely still be running, however, this
nonblocking behaviour allows the controller to return immediately, which
is required when handling an <code class="classname">HttpRequest</code>. An
example is below:</p><pre class="programlisting">@Controller
public class JobLauncherController {
@Autowired
JobLauncher jobLauncher;
@Autowired
Job job;
@RequestMapping("/jobLauncher.html")
public void handle() throws Exception{
jobLauncher.run(job, new JobParameters());
}
}</pre></section></section><footer/></body></html>