What's the point of Spring Batch's JobLocator? - spring

I've created a Spring Batch application (together with Spring Boot). Configuring a Job works well, and each Job is executed at startup. The job configurations also show up in the database as expected.
To launch a Job with parameters, there are two options:
Inject the Job as it is a Java Bean - works great
Use JobLocator to get a instance of the Job - seen in several tutorials, but does not work ("No job configuration with the name [doSomethingJob] was registered")
So my question is: What's the point of a JobLocator if one can easily inject jobs directly?

The JobLocator isn't for injection of jobs. It's to locate an instance to execute. If you have something that will be executing jobs dynamically (not knowing what job it will need to execute), you'll want to use a JobLocator. An example of this is in Spring Batch Admin. There, a JobLocator is used from within the JobService to get the requested Job to launch.
Wiring a Job instance into your class works well when it's predetermined what job you'll be running. However, if you don't, the JobLocator is the way to go.

Related

Spring task:scheduled or #Scheduler to restrict a Job to run in multiple instance

I have one #Scheduler job which runs on multiple servers in a clustered environment. However I want to restrict the job to run in only in one server and other servers should not run the same job once any other server has started it .
I have explored Spring Batch has lock mechanism using some Database table , but looking for any a solution only in spring task:scheduler.
I had the same problem and the solution what I implemented was a the Lock mechanism with Hazelcast and to made it easy to use I also added a proper annotation and a bit of spring AOP for that. So with this trick I was able to enforce a single schedule over the cluster done with a single annotation.
Spring Batch has this nice functionality that it would not run the job with same job arguments twice.
You can use this feature so that when a spring batch job kicks start in another server it does not run.
Usually people pass a timestamp as argument so it will by pass this logic, which you can change it.

When spring-boot app multi-node deploy, how to handle cron job?

When I use spring task handle a simple sync job! But when I deploy multi-node, how I make sure the cron job just run one time.
Maybe you say that:
1. Use distributed-lock control a flag before the crob job run.
2. Integrated quartz cluster function.
But I hope spring task #EnableScheduling can add a flag argument, so as we can set a flag when launch app.
We are using https://github.com/lukas-krecan/ShedLock with success, zookeeper provider in particular.
Spring boot, in a nutshell, doesn't allow any type of coordination between multiple instances
of the same microservice.
All the work of such a coordination is done by the third parties that spring boot gets integrated with.
One example of this is indeed a #Scheduled annotation.
Another is DB migration support via flyway.
When many nodes start and the migration has to be done, flyway is responsible to lock the migration table by itself, spring boot has nothing to do with it.
So, bottom line, there is no such support and all options that you've raised can work.

Spring batch - stop job running in different JRE

Background:
I created a Stop Job which finds running jobs with the specified name as this:
jobExplorer.findRunningJobExecutions("job_A")
and then, for each execution of job_A it calls:
jobOperator.stop(execution.getId());
Issue
when i call the above stop() method; even though it eventually accomplishes what i want, but it still throws an exception:
WARN o.s.b.c.l.s.SimpleJobOperator [main] Cannot find Job object
org.springframework.batch.core.launch.NoSuchJobException: No job configuration with the name [job_A] was registered
at org.springframework.batch.core.configuration.support.MapJobRegistry.getJob(MapJobRegistry.java:66) ~[spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobOperator.stop(SimpleJobOperator.java:403) [spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]
The Cause
This happens when the stop() method tries to located job_A in the JobRegistry.
So even though job_A was found in the "JobRepository" because the repository looks in the database, it was not found in the "JobRegistry" which is a local cache of job beans created within its runtime environment, since job_A is running withing a different runtime instance it was not registered and threw and error.
Concern
Even though job 'A' stops i am still concerned what i have missed because of the exception.
I have searched this issue and found only general answers on how to stop a job, however i did not find anyone explaining how to stop a running job of another runtime.
Any answers would be greatly appreciated.
The JobOperator isn't intended to orchestrate distributed batch environments like you're attempting to do. You really have two options:
Use the JobRepository directly - The part that causes the job to stop successfully in the remote JVM is that the JobRepository is updated and the running job in the other JVM knows to check that periodically. Instead of using the JobOperator to accomplish this, just use the JobRepository directly to make the update.
Use a more robust orchestration tool like Spring Cloud Data Flow - This kind of orchestration (deploying, starting, stopping, etc) for jobs (via Spring Cloud Task) is what Spring Cloud Data Flow is for.
You can read more about Spring Cloud Data Flow at the website: https://cloud.spring.io/spring-cloud-dataflow/
In addition to what Michael mentioned you can solve this by adding some interface to the application allowing you to pass commands to start or stop your job. Something like a webservice. Exposing an end-point to stop it. Now the catch in this case is handling in clustered system may be a bit tricky.

What is the difference between spring scheduled tasks and spring batch jobs

I dont understand the difference between scheduled tasks and batch jobs in spring.
By scheduled tasks I mean the ones which are configured like these:
#EnableScheduling
public class AppConfig{
..
and used like
#Scheduled(fixedRate=550)
public void doSomething(){
..
By batch jobs I mean these:
#EnableBatchProcessing
public class AppConfig{
..
and lots of implementations like:
Jobs, Job launcher, Steps, ItemReader, ItemWriter... etc
I would like to know the main difference between them besides the implementation differences and also I am curious why to use batch jobs and make a lot of long implementations while we can use simple scheduled tasks. I mean the implementation of scheduled jobs is quite easy but maybe they had disadvantages according to the batch jobs?
Spring Scheduler is for orchestrating something based on a schedule. Spring Batch is a robust batch processing framework designed for the building of complex compute problems. Spring Batch does not handle the orchestration of jobs, just the building of them. You can orchestrate Spring Batch jobs with Spring Scheduler if you want.
2 aspects which i can think of: afaik when a job-run fails, in 2. run, it will run with the same job parameters.. at least you can configure this i think. and this kind of error situations which you can configure more easily than writing all in code in the same place manually (your scheduled method). Secondly, maybe batch gives a structure to your code when you also have to read your data from somewhere, and write somewhere... batch has some kind of reader, processor, writer schema.. Also some automatically created database tables (BATCH_JOB_INSTANCE) and batch job results.. like when the job started etc...
Edit: More Reasons for a batch: large amount of data, Transaction management, Chunk based processing, Declarative I/O, Start/Stop/Restart, Retry/Skip, Web based administration interface.

Spring + Quartz + JobStoreCMT

I need help with quartz + jdbc Jobstore.
Situation looks that:
I have spring application, and within this application there is quartz scheduler, it use persistence jobstore (JobStoreCMT with oracle Database). When i need to do some scheduled job, basicly I'm creating class with my annotation, where I'm writing for exapmle cron expression. When application starting, for all classes annotated like this are creating jobs, and scheduling with quartz.
When i don't want some job, i'm deleting his class, and there isn't loaded on startup. But what to do with already scheduled Job. When i'm starting my application without this Job Class, quartz want to recovery this job from Database JobStore, but this class is not exist, so i gets exeption.
Is there any way to 'tell' quartz, that if job class doesn't exist, quartz should deleted it from scheduler ?
There exists a deleteJob() method in the Scheduler class in order to delete Jobs.
See http://quartz-scheduler.org/api/1.8.5/
You could also use getJobNames() to know if one of your jobs is missing.

Resources