Java EE 7 added the capability to perform Batch jobs in a standard way using JSR 352.
1
2
3
4
5
6
7
|
<job id="myJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
<step id="myStep">
<chunk item-count="3">
<reader ref="myItemReader"/>
<processor ref="myItemProcessor"/>
<writer ref="myItemWriter"/>
</chunk>
|
This code fragment is the Job Specification Language defined as XML, a.k.a. Job XML. It defines a canonical job, with a single step, using item-oriented or chunk-oriented processing. A chunk can have a reader, optional processor, and a writer. Each of these elements are identified using the corresponding elements in the Job XML, and are CDI beans packaged in the archive.
This job can be easily started using:
1
|
BatchRuntime.getJobOperator().start("myJob", new Properties());
|
A typical question asked in different forums and conferences is how to schedule these jobs in a Java EE runtime. Batch 1.0 API itself does not offer anything to be schedule these jobs. However Java EE platform offers three different ways to schedule these jobs:
- Use the
@javax.ejb.Schedule
annotation in an EJB.
Here is a sample code that will trigger the execution of batch job at 11:59:59 PM every day.
1234567@Singletonpublic class MyEJB {@Schedule(hour = "23", minute = "59", second = "59")public void myJob() {BatchRuntime.getJobOperator().start("myJob", new Properties());}}
Of course, you can change the parameters of@Schedule
to start the batch job at the desired time. - Use
ManagedScheduledExecutorService
usingjavax.enterprise.concurrent.Trigger
as shown:
1234567891011121314151617181920212223242526@Statelesspublic class MyStatelessEJB {@ResourceManagedScheduledExecutorService executor;public void runJob() {executor.schedule(new MyJob(), new Trigger() {public Date getNextRunTime(LastExecution lastExecutionInfo, Date taskScheduledTime) {Calendar cal = Calendar.getInstance();cal.setTime(taskScheduledTime);cal.add(Calendar.DATE, 1);return cal.getTime();}public boolean skipRun(LastExecution lastExecutionInfo, Date scheduledRunTime) {return null == lastExecutionInfo;}});}public void cancelJob() {executor.shutdown();}}
CallrunJob
to initiate job execution andcancelJob
to terminate job execution. In this case, a new job is started a day later than the previous task. And its not started until previous one is terminated. You will need more error checks for proper execution.MyJob is very trivial:
1234567public class MyJob implements Runnable {public void run() {BatchRuntime.getJobOperator().start("myJob", new Properties());}}Of course, you can automatically schedule it by calling this code in
@PostConstruct
. - A slight variation of second technique allows to run the job after a fixed delay as shown:
123public void runJob2() {executor.scheduleWithFixedDelay(new MyJob(), 2, 3, TimeUnit.HOURS);}
The first task is executed 2 hours after the
runJob2
method is called. And then with a 3 hours delay between subsequent execution.
This support is available to you within the Java EE platform. In addition, you can also invoke BatchRuntime.getJobOperator().start("myJob", new Properties());
from any of your Quartz-scheduled methods as well.
You can try all of this on WildFly.
And there are a ton of Java EE 7 samples at github.com/javaee-samples/javaee7-samples.
This particular sample is available at github.com/javaee-samples/javaee7-samples/tree/master/batch/scheduling.
How are you scheduling your Batch jobs ?
Thanks, nice tip.
It’s not very clear to me what this job does or what it’s supposed to do.
I got the part about scheduling it.
Could you explain it to me?
I am not sure #3 is a good option. Because you directly instantiated MyJob, you won’t get dependency injection, right?
Agreed. In general, you want to inject your resources
Where do I have to place the XML? …/resouces/META-INF/batch-jobs/jobs.xml ?
By the way, your XML is not well formed, there are 2 tag closures that are missing.