Schedule job using cron expression from class field - java

I tried to find it, but without results. I'd like to have object having path to bash script and cron expression specifying when to run it. It's SpringBoot project. I see it like this:
public class TestScript {
private String cronExpression;
private String pathToFile;
public void execute() {
// either it's #Scheduled or execute another way
}
}
Is it possible to do? Please guide me even a little if you can.

Ok, I managed to make my custom service that dynamically creates jobs:
#Service
public class DynamicJob {
public void schedule(TestScript testScript) {
try {
JobDetail job = JobBuilder.newJob(TestScript.class)
.withIdentity(testScript.getName(), "default group")
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(testScript.getName().concat(" trigger"), "groupAll")
.withSchedule(CronScheduleBuilder.cronSchedule(testScript.getCronExpression()))
.build();
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();
scheduler.scheduleJob(job, trigger);
} catch (Exception e) {
e.printStackTrace();
}
}
}
TestScript class implements org.quartz.Job and I use quartz library version 2.2.1

Related

Get the spring boot scheduled cron expression from outside jar file

I have a spring boot java service I have to schedule to run on a particular time. I have enabled the #Enablescheduling and #Scheduled annotation and given the cron expression.
It's working fine. The scheduler is running at the expected time. But my concern is I should control the cron expression somewhere from outside my jar file. I have tried using it in property file but when packaging my property file also getting included in that.
Sample code:
#PostMapping(path = "getoktatodynamodb")
#Scheduled(cron = "0 0/5 0 * * ?")
#ApiOperation("Sync data to DynamoDB")
public FinalResponse getdatatodynamodb() {
FinalResponse finalResponse = new FinalResponse();
try {
LOGGER.info("Sync data to DynamoDB starts - " + new Date());
finalResponse = dynamodbuserService.dynamoDbSync();
} catch (MyRestTemplateException ex) {
LOGGER.error(ex.getMessage());
finalResponse.setResponseMessage(ex.getMessage());
finalResponse.setStatusCode(ex.getStatusCode().value());
} catch (Exception execption) {
LOGGER.error(execption.getMessage());
finalResponse.setResponseMessage(execption.getMessage());
finalResponse.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
} finally {
LOGGER.info("Sync data DynamoDB Ends - " + new Date());
}
return finalResponse;
}
The main intention is scheduler should be in our control whenever we need to change the time it should be configurable. No code change and restarting the scheduler for minor changes.
How should we achieve this also we would like to schedule this in linux ec2 instance? in case if we have better suggestion to achieve this kindly share it.
You can implement SchedulingConfigurer:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/SchedulingConfigurer.html
This DZone article shows a really good example: https://dzone.com/articles/schedulers-in-java-and-spring which I'm showing here in case the article doesn't stay permanent.
#Configuration
#EnableScheduling
public class ScheduledConfiguration implements SchedulingConfigurer {
TaskScheduler taskScheduler;
private ScheduledFuture<?> job1;
private ScheduledFuture<?> job2;
#Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler threadPoolTaskScheduler =new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(10);// Set the pool of threads
threadPoolTaskScheduler.setThreadNamePrefix("scheduler-thread");
threadPoolTaskScheduler.initialize();
job1(threadPoolTaskScheduler);// Assign the job1 to the scheduler
// Assign the job1 to the scheduler
this.taskScheduler=threadPoolTaskScheduler;// this will be used in later part of the article during refreshing the cron expression dynamically
taskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
}
private void job1(TaskScheduler scheduler) {
job1 = scheduler.schedule(new Runnable() {
#Override
public void run() {
System.out.println(Thread.currentThread().getName() + " The Task1 executed at " + new Date());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, new Trigger() {
#Override
public Date nextExecutionTime(TriggerContext triggerContext) {
String cronExp = "0/5 * * * * ?";// Can be pulled from a db .
return new CronTrigger(cronExp).nextExecutionTime(triggerContext);
}
});
}
private void job2(TaskScheduler scheduler){
job2=scheduler.schedule(new Runnable(){
#Override
public void run() {
System.out.println(Thread.currentThread().getName()+" The Task2 executed at "+ new Date());
}
}, new Trigger(){
#Override
public Date nextExecutionTime(TriggerContext triggerContext) {
String cronExp="0/1 * * * * ?";//Can be pulled from a db . This will run every minute
return new CronTrigger(cronExp).nextExecutionTime(triggerContext);
}
});
}
}

Quartz job scheduler using Java, stuck on standby mode without the job being executed

i have a class where i perform some activities, and i want to create a job that will handle this operation automatically, scheduled every x minutes for example.
I am using Quartz, this class implements Job, and in my driver class i'm creating my jobdetail, scheduler and trigger and then starting it. However, the job isn't being executed, log info :
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
The code for the scheduler in my driver class:
try {
JobDetail job = JobBuilder.newJob(TestMkFPMJob.class).withIdentity("TestMkFPMJob").build();
Trigger trigger = TriggerBuilder.newTrigger().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(Integer.parseInt(strTimeSched)).repeatForever()).build();
SchedulerFactory schFactory = new StdSchedulerFactory();
Scheduler sch = schFactory.getScheduler();
sch.start();
sch.scheduleJob(job, trigger);
}
catch (SchedulerException e)
{
e.printStackTrace();
System.out.println("Scheduler Error");
}
With "TestMkFPMJob" being the job class where my operations are handled, and strTimeSched is already fetched and set as 120 fetched from
I've been looking for a similar issue but can't seem to find any tip to move forward, appreciate any.
Please note that this is my first time using Quartz/Job scheduling.
The log entry with NOT STARTED is misleading, as it is shown whenever a QuartzScheduler instance is created. It does not mean that the jobs are not running. It is written after the line Scheduler sch = schFactory.getScheduler(); is executed and the scheduler is started in the next line.
If I take your example and run it on my pc, it is working as designed:
public class Quartz {
public static void main(String[] args) {
try {
JobDetail job = JobBuilder.newJob(MyJob.class).withIdentity("myJob").build();
Trigger trigger = TriggerBuilder.newTrigger().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(Integer.parseInt("10")).repeatForever()).build();
SchedulerFactory schFactory = new StdSchedulerFactory();
Scheduler sch = schFactory.getScheduler();
sch.start();
sch.scheduleJob(job, trigger);
}
catch (SchedulerException e)
{
e.printStackTrace();
System.out.println("Scheduler Error");
}
}
public static class MyJob implements Job {
#Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("runnning job");
}
}
}

Execute a Quartz Job only once in a multi-instance environment

I'm trying to create a Job in Quartz 1.6, but with the necessity to execute only once, because I have two test instances with the same version of a .war file.
This is my TestPlugin class, the Job will be executed every 60 seconds:
public class TestPlugin implements PlugIn {
public TestPlugin() {
super();
}
public void destroy() {
}
public void init(ActionServlet arg0, ModuleConfig arg1)
throws ServletException {
try {
JobDetail job = JobBuilder.newJob(TestDemonio.class)
.withIdentity("anyJobName", "group1").build();
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("anyTriggerName", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule("0/60 * * ? * * *"))
.build();
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.scheduleJob(job, trigger);
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
Then I have my class TestExecute to print a simple output:
#DisallowConcurrentExecution
public class TestDemonio implements Job {
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println("QUARTZ JOB MESSAGE");
}
}
I have researched on how to achieve what I want by adding the annotation #DisallowConcurrentExecution, to only execute once the job, but I receive a message printed on each instance.
This is my quartz.properties file:
# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
org.quartz.jobStore.misfireThreshold: 60000
org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
You need to add following property to your quartz.property file(source: click here):
org.quartz.jobStore.isClustered : true
Read this for more information about isClustered property, refer to this link.
Please note:
#DisallowConcurrentExecution works when you have 2 different jobs with same jobkey running on same node.
While isClustered property is used to make sure that single instance of a job is executed when app is running of multiple nodes communicating via database tables for atomicity.

How to run .bat file using spring boot batch process

I have a batch file which is running through windows task scheduler and it will he execute the jar file every 10 hours repeately.
Now, I'm trying to run the same batch file using spring boot batch process as a task scheduler. but i didn't get solution for this.
How can i resolve the this issue?
In your schedule method, try like this:
Runtime.getRuntime().exec("file.bat");
Did you try this https://spring.io/guides/gs/scheduling-tasks/
Spring Boot scheduler can schedule your tasks and accepts CRON like expression to scheduling recurring tasks.
You can use Java ProcessBuilder API to trigger your batch (.bat) file
You can implement simple Spring scheduling tasks as following
#Component
public class RunCommandScheduledTask {
private final ProcessBuilder builder;
private final Logger logger; // Slf4j in this example
// inject location/path of the bat file
#Inject
public RunCommandScheduledTask(#Value("${bat.file.path.property}") String pathToBatFile) {
this.builder = new ProcessBuilder(pathToBatFile);
this.logger = LoggerFactory.getLogger("RunCommandScheduledTask");
}
// cron to execute each 10h
#Scheduled(cron = "0 */10 * * *")
public void runExternalCommand() {
try {
final Process process = builder.start();
if (logger.isDebugEnabled()) {
// pipe command output and proxy it into log
try (BufferedReader out = new BufferedReader(
new InputStreamReader(process.getInputStream(), StandardCharsets.ISO_8859_1))) {
String str = null;
for (;;) {
str = out.readLine();
if (null == str)
break;
logger.debug(str);
}
}
}
process.waitFor();
} catch (IOException exc) {
logger.error("Can not execute external command", exc);
} catch (InterruptedException exc) {
Thread.currentThread().interrupt();
}
}
}
.....
#SpringBootApplication
#EnableScheduling
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class);
}
}

Simple Quartz/Cron job setup

I'm using Quartz to write a simple server monitor in Java:
public class ServerMonitorJob implements Job {
#Override
public void execute(JobExecutionContext ctx) {
// Omitted here for brevity, but uses HttpClient to connect
// to a server and examine the response's status code.
}
}
public class ServerMonitorApp {
private ServerMonitorJob job;
public ServerMonitorApp(ServerMonitorJob jb) {
super();
this.job = jb;
}
public static void main(String[] args) {
ServerMonitorApp app = new ServerMonitorApp(new ServerMonitorJob());
app.configAndRun();
}
public void configAndRun() {
// I simply want the ServerMonitorJob to kick off once
// every 15 minutes, and can't figure out how to configure
// Quartz to do this...
// My initial attempt...
SchedulerFactory fact = new org.quartz.impl.StdSchedulerFactory();
Scheduler scheduler = fact.getScheduler();
scheduler.start();
CronTigger cronTrigger = new CronTriggerImpl();
JobDetail detail = new Job(job.getClass()); // ???
scheduler.schedule(detail, cronTrigger);
scheduler.shutdown();
}
}
I think I'm somewhere around the 70% mark; I just need help connecting the dots to get me all the way there. Thanks in advance!
You are almost there:
JobBuilder job = newJob(ServerMonitorJob.class);
TriggerBuilder trigger = newTrigger()
.withSchedule(
simpleSchedule()
.withIntervalInMinutes(15)
);
scheduler.scheduleJob(job.build(), trigger.build());
Check out the documentation, note that you don't need a CRON trigger when you simply want to run the job every 15 minutes.

Categories

Resources