This article is based on SpringBatch in Action, to be published July-2011. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) ebooks and pbooks. MEAPs are sold exclusively through Manning.com. All print book purchases include an ebook free of charge. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information.
You’re about to see that launching a Spring Batch job is quite simple thanks to the Spring Batch launcher API. But, how you end up launching your batch jobs depends on many parameters, so we provide you with basic concepts and some guidelines. By the end of this article, you’ll know where to look to set up a launching environment for your jobs. If you are interested in learning more tutorials on spring, please read spring tutorials.
also read:
Introducing the Spring Batch launch API
The heart of the Spring Batch launcher API is the JobLauncher interface. Here is a shortened version of this interface (we removed the exceptions for brevity):
public interface JobLauncher { public JobExecution run(Job job, JobParameters jobParameters) throws (…); }
The JobLauncher itself and the Job you pass to the run method are Spring beans. The call site typically builds the JobParameters argument on the fly. The following snippet shows how to use the job launcher to start a job execution with two parameters:
JobLauncher jobLauncher = context.getBean(JobLauncher.class); Job job = context.getBean(Job.class); jobLauncher.run( job, new JobParametersBuilder() .addString("inputFile", "file:./products.txt") .addDate("date", new Date()) .toJobParameters() );
Note the use a JobParametersBuilder to create a JobParameters instance. The JobParametersBuilder class provides a fluent-style API to construct job parameters. A job parameter consists of a key and a value. Spring Batch supports four types for job parameters: string, long, double, and date.
Job parameters and job instance Remember that job parameters define the instance of a job and that a job instance can have one or more corresponding executions. You can view an execution as an attempt to run a batch process.
Spring Batch provides an implementation of JobLauncher, whose only mandatory dependency is a job repository. The following snippet shows how to declare a job launcher with a persistent job repository:
<batch:job-repository id="jobRepository" data-source="dataSource" /> <bean id="jobLauncher" class="org.springframework. [CA] batch.core.launch.support.SimpleJobLauncher"> <property name="jobRepository" ref="jobRepository" /> </bean>
That’s it; you know everything about the Spring Batch launcher API! Ok, not everything, we did not describe the JobExecution object returned by the run method. As you can guess, this object represents the execution coming out of the run method. The JobExecution interface provides the API to query the status of an execution: if it’s running, if it has finished or if it has failed. Because batch processes are often quite long to execute, Spring Batch offers both synchronous and asynchronous ways to launch jobs.
Synchronous vs. asynchronous launches
By default, the JobLauncher run method is synchronous: the caller waits until the job execution ends (successfully or not.) Figure 1 illustrates a synchronous launch.
Synchronous launching is good in some cases: if you write a Java main program that a system scheduler like cron launches periodically, you want to exit the program only when the execution ends. But, imagine that an HTTP request triggers the launching of a job. Writing a web controller that uses the job launcher to start Spring Batch jobs on HTTP requests is a handy way to integrate with external triggering systems. What happens if the launch is synchronous? The batch process will execute in the calling thread, monopolizing web container resources. Submit many batch processes in this way and they will use up all the threads of the web container, making it unable to process any other requests.
The solution is to make the job launcher asynchronous. Figure 2 shows how launching behaves when the job launcher is asynchronous.
To make the job launcher asynchronous, just provide it with an appropriate TaskExecutor, as shown in the following snippet:
<task:executor id="executor" pool-size="10" /> <bean id="jobLauncher" class="org.springframework. [CA] batch.core.launch.support.SimpleJobLauncher"> <property name="jobRepository" ref="jobRepository" /> <property name="taskExecutor" ref="executor" /> </bean>
In this example, we use a task executor with a thread pool of size 10. The executor will reuse threads from its pool to launch job executions asynchronously. Note the use of the executor XML element from the task namespace. This is a shortcut provided in Spring 3.0, but you can also define a task executor like any other bean (using an implementation like ThreadPoolTaskExecutor).
It is now time to guide you through the launching solutions.
Overview of launching solutions
We’ll now discuss many solutions to launch your Spring Batch jobs. There’s little chance you’ll use them all in one project. Many factors can lead you to choose a specific launching solution: launching frequency, number of jobs to launch, nature of the triggering event, type of job, duration of the job execution, and so on. Let’s explore some cases and present some guidelines.
Launching from the command line
A straightforward way to launch a Spring Batch job is to use the command line, which spawns a new Java Virtual Machine process for the execution, as figure 3 illustrates.
The triggering event can be a system scheduler like cron or even a human operator that knows when to launch the job. You’ll see that you can write your own Java launcher program but also that Spring Batch provides a generic command line launcher that you can reuse.
Embedding Spring Batch and a scheduler in a container
Spawning a JVM process for each execution can be costly, especially if it opens new connections to a database or creates object-relational mapping contexts. Such initializations are resource intensive and you probably don’t want the associated costs if your jobs run every minute. Another option is to embed Spring Batch into a container such that your Spring Batch environment is ready to run at any time and there is no need to set up Spring Batch for each job execution. You can also choose to embed a Java-based scheduler to start your jobs. Figure 4 illustrates this solution.
A web container is a popular way to embed a Spring Batch environment. Remember that Spring Batch runs everywhere the Spring Framework runs.
Embedding Spring Batch and triggering jobs by an external event
You can also have a mix of solutions: use cron because it is a popular solution in your company and embed Spring Batch in a web application because it avoids costly recurring initializations. The challenge here is to give cron access to the Spring Batch environment. Figure 5 illustrates this deployment.
The list of launching solutions we cover here is by no means exhaustive. The Spring Batch launcher API is simple to use, so you can imagine building other types of solutions, for example: event-driven with JMS or remote with JMX.
also read:
Summary
Launching Spring Batch jobs is easy. We covered some of the many scenarios, which are the most common scenarios you’ll meet in batch systems. With Spring Batch, you can stick to the popular cron + command line scenario using either your own Java program or Spring Batch’s generic command line runner. You can also choose to embed Spring Batch in a web application combined with a Java scheduler.