This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Batch Documentation 5.2.2!

Running a Job

At a minimum, launching a batch job requires two things: the Job to be launched and a JobOperator. Both can be contained within the same context or different contexts. For example, if you launch jobs from the command line, a new JVM is instantiated for each Job. Thus, every job has its own JobOperator. However, if you run from within a web container that is within the scope of an HttpRequest, there is usually one JobOperator (configured for asynchronous job launching) that multiple requests invoke to launch their jobs.

Running Jobs from the Command Line

If you want to run your jobs from an enterprise scheduler, the command line is the primary interface. This is because most schedulers (with the exception of Quartz, unless using NativeJob) 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 focuses on them.

The CommandLineJobOperator

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 this purpose: CommandLineJobOperator. Note that this is just one way to bootstrap your application. There are many ways to launch a Java process, and this class should in no way be viewed as definitive. The CommandLineJobOperator performs four tasks:

  • Load the appropriate ApplicationContext.

  • Parse command line arguments into JobParameters.

  • Locate the appropriate job based on arguments.

  • Use the JobOperator provided in the application context to launch the job.

All of these tasks are accomplished with only the arguments passed in. The following table describes the required arguments:

Table 1. CommandLineJobOperator arguments

jobClass

The fully qualified name of the job configuration class used to create an ApplicationContext. This file should contain everything needed to run the complete Job.

operation

The name of the operation to execute on the job. Can be one of [start, startNextInstance, stop, restart, abandon]

jobName or jobExecutionId

Depending on the operation, this can be the name of the job to start or the execution ID of the job to stop, restart or abandon.

When starting a job, all arguments after these are considered to be job parameters, are turned into a JobParameters object, and must be in the format of name=value. In the case of stopping, restarting or abandoning a job, the jobExecutionId is expected as the 4th argument, and all remaining arguments are ignored.

The following example shows a date passed as a job parameter to a job defined in Java:

<bash$ java CommandLineJobOperator io.spring.EndOfDayJobConfiguration start endOfDay schedule.date=2007-05-05,java.time.LocalDate

By default, the CommandLineJobOperator uses a DefaultJobParametersConverter that implicitly converts key/value pairs to identifying job parameters. However, you can explicitly specify which job parameters are identifying and which are not by suffixing them with true or false, respectively.

In the following example, schedule.date is an identifying job parameter, while vendor.id is not:

<bash$ java CommandLineJobOperator io.spring.EndOfDayJobConfiguration start endOfDay \
                                 schedule.date=2007-05-05,java.time.LocalDate,true \
                                 vendor.id=123,java.lang.Long,false

You can override this behavior by setting a custom JobParametersConverter on the CommandLineJobOperator.

Exit Codes

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 invoke). 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 to indicate the result of the run. In the simplest case, 0 is success and 1 is failure. However, there may be more complex scenarios, such as “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 ExitStatus, 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 ExitStatus has an exit code property that is set by the framework (or the developer) and is returned as part of the JobExecution returned from the JobOperator. The CommandLineJobOperator converts this string value to a number by using the ExitCodeMapper interface:

public interface ExitCodeMapper {

    int intValue(String exitCode);

}

The essential contract of an ExitCodeMapper 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 Job in the provided context. If anything more complex than the three values above is needed, a custom implementation of the ExitCodeMapper interface must be supplied by setting it on the CommandLineJobOperator.

Running Jobs from within a Web Container

Historically, offline processing (such as batch jobs) has been launched from the command-line, as described earlier. However, there are many cases where launching from an HttpRequest 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 to launch the job asynchronously:

Async Job Launcher Sequence from web container
Figure 1. Asynchronous Job Launcher Sequence From Web Container

The controller in this case is a Spring MVC controller. See the Spring Framework Reference Guide for more about Spring MVC. The controller launches a Job by using a JobOperator that has been configured to launch asynchronously, which immediately returns a JobExecution. The Job is likely still running. However, this nonblocking behavior lets the controller return immediately, which is required when handling an HttpRequest. The following listing shows an example:

@Controller
public class JobOperatorController {

    @Autowired
    JobOperator jobOperator;

    @Autowired
    Job job;

    @RequestMapping("/jobOperator.html")
    public void handle() throws Exception{
        jobOperator.start(job, new JobParameters());
    }
}