Making scheduler application specific and not server specific - spring

We have to bind the scheduler Thread to application context.
I tried using #PostConstruct but it starts the scheduler once application is up but it keeps running in the background even if application is down and server is up.
If application is down then the scheduler should also stop.

The way I used Scheduler in Spring (i.e. Spring Boot) is by having two classes inside my project (& therefore included in my .jar after build).
1 - SchedulerConfig (necessary for the configuration)
#Configuration
public class SchedulerConfig implements SchedulingConfigurer {
private final int POOL_SIZE = 10;
#Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(POOL_SIZE);
threadPoolTaskScheduler.setThreadNamePrefix("my-scheduled-task-pool-");
threadPoolTaskScheduler.initialize();
scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
}
}
2 - ScheduledTasks (the actual scheduled tasks with frequency defined by the cron expression)
#Component
public class ScheduledTasks {
private static final Logger LOG = Logger.getLogger(ScheduledTasks.class);
#Scheduled(cron = "0 0 * ? * *")
public void doSomething() {
// Do something
}
}
Therefore, as everything is included in the running .jar, when the application is not deployed any more, scheduled tasks will not run as well.
See also https://www.baeldung.com/spring-scheduled-tasks

Related

Spring #Schleduled annotation does not work

I want a spring scheduled task, that runs every 10 seconds, however for some reason the task runs only once and is never repeated again.
Please do not suggest me to use other types of tasks, because I need specifically to use spring tasks.
#Scheduled(fixedRate = 10000, initialDelay = 1000)
public void myTask() {
...
}
In my main config class I have #EnableScheduling added as well.
Scheduling is a process of executing the tasks for a specific time period, but you looking to make it asynchrounslly so there will be a couple of changes
create a config class that will manage the Async operations so you make use of ThreadPoolTaskExecutor:
#EnableScheduling
#Configuration
public class TaskConfig implements SchedulingConfigurer {
#Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar)
{
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(10);
threadPoolTaskScheduler.setThreadNamePrefix("your-scheduler-");
threadPoolTaskScheduler.initialize();
scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
}
}
then you can run jobs asynchrounslly as the below :
#Component
public class HelloSender {
#Scheduled(fixedRate = 10000)
public void myTask() {
System.out.println("im running asynchronous with Worker : " + Thread.currentThread().getName());
}
}
for further information about ThreadPoolTaskExecutor please have look here: https://docs.spring.io/spring-framework/docs/3.0.x/spring-framework-reference/html/scheduling.html

spring #Scheduled annotaion works on Local Websphere but does not work on Websphere installed on Severs

Spring #Scheduled(cron = "${cron expression}") works on the websphere in local machine but not on the non prod servers.
You should check the Thread pool in the different Webshere to check whats the difference I asume your problem might be there.
Else, a more complicated solution is to pass in a custom threadpool for your schedule tasks.
To do this create a new configuration class for the Scheduler and add a custom Threadpool
#Configuration
public class SchedulerConfig implements SchedulingConfigurer {
private final int POOL_SIZE = 10;
#Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(POOL_SIZE);
threadPoolTaskScheduler.setThreadNamePrefix("my-scheduled-task-pool-");
threadPoolTaskScheduler.initialize();
scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
}
}
You can find more references here https://www.callicoder.com/spring-boot-task-scheduling-with-scheduled-annotation/

Does a stand-by Quartz Scheduler require some kind of refresh for starting?

I'm using Quartz with Spring Boot, specifically using it's conveniences through the SchedulerFactoryBean abstraction. See https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-quartz.html.
I need to start the Scheduler manually instead, for which I think of using schedulerFactoryBean.setAutoStartup(false) and then Scheduler.start() in a class with an Scheduler instance autowired. See example code below.
#Configuration
public class QuartzConfig implements SchedulerFactoryBeanCustomizer {
public static final int STARTUP_DELAY = 5;
#Autowired
private DataSource dataSource;
#Override
public void customize(SchedulerFactoryBean schedulerFactoryBean) {
schedulerFactoryBean.setDataSource(dataSource);
schedulerFactoryBean.setStartupDelay(STARTUP_DELAY);
schedulerFactoryBean.setAutoStartup(false);
schedulerFactoryBean.setWaitForJobsToCompleteOnShutdown(TRUE);
}
}
#Service
public class SchedulerService {
private final Scheduler scheduler;
#Autowired
public SchedulerService(Scheduler scheduler) {
this.scheduler = scheduler;
}
public void startScheduler() {
this.scheduler.start();
}
}
However, there will be other instances in other nodes running on the database. My question is, does this not-started Scheduler instance refresh or becomes aware of all the work done by the other instance? Does a stand-by Quartz Scheduler require some kind of refresh manually triggered for starting?
For example, if a trigger, job or something else is added, changed or deleted will the not-started one be aware (cache refresh?) of it after the code calls .start()?
I have read several pages of quartz and I couldnt really find an aswer for this. I couldnt find a place that explains if or how an instance sincronizes itself with external changes done to its database.

Spring Boot is throwing a null for JPA Repository if I use the quartz scheduler to start manually

I'm having a Quartz Scheduler as part of a Spring boot application. I'm loading the SchedulerFactory from a #Configuration file. This is the setup I have:
Config.java:
#Configuration
public class Config {
#Bean(name="stdSchedulerFactory_api")
public StdSchedulerFactory getStdSchedulerFactory() throws SchedulerException{
return new StdSchedulerFactory("/etc/quartz.properties");
}
}
The quartz.properties file contains location to a file containing the list of jobs to perform. This is how it is configured in the properties file:
org.quartz.plugin.jobInitializer.fileNames =/etc/quartz-config.xml
And the quartz-config.xml has the jobs listed as below:
<job>
<name>MasterScheduleJob</name>
<group>MasterScheduleJobGroup</group>
<description>This is Master Job Scheduler</description>
<job-class>com.MasterScheduler</job-class>
<durability>true</durability>
<recover>false</recover>
</job>
Master.java
#Component
#Scope("singleton")
public class Master {
#PostConstruct
public static void init(){
// Get SchedulerFactory context from Config file and start the scheduler
SchedulerFactory factory = null;
factory = (StdSchedulerFactory) context.getBean("stdSchedulerFactory_api");
scheduler = factory.getScheduler();
setScheduler(scheduler);
scheduler.start();
}
}
When the Master starts, it reads the Quartz-config.xml file, and in turn calls the MasterScheduler.java which is below:
MasterScheduler.java
#Service
#PersistJobDataAfterExecution
#DisallowConcurrentExecution
public class MasterScheduler implements Job {
#Autowired
public JobsScheduleRepository jobsScheduleRepository;
private List<JobsScheduleDAO> jobsScheduleDAO;
#Override
public void execute(JobExecutionContext jobContext) {
jobsScheduleDAO = jobsScheduleRepository.findAll();
}
}
When I run this code, I get a null pointer exception saying jobsScheduleRepository is null. I'm suspecting this is because the Quartz scheduler starts MasterScheduler.java using new() internally. I do not want to use the Quartz scheduler provided by Spring. Is there any other alternative?
If there is a way to avoid using #Autowired and access the repository directly, I can use that as a temporary fix for now.

Spring Scheduler

I go through spring Scheduler support documentation.
where I found:
ScheduledFuture schedule (Runnable task, Date startTime);
But in case of #EnableScheduling there is no Thread Implementation in various examples.
Why??
any one can explain
Thanks in advance.
With #EnableScheduling you just enable the spring scheduler functionality.
To run a task you would annotate a public method with #Scheduled.
So you see that you dont need a runnable / thread for this as your annotabed method will be called using reflection.
#EnableScheduling
public class Tasks {
#Scheduled(... options here)
public void myTasks(){
//doSomethingHere...
}
}
our class must have at least these annotations :
package org.springframework.scheduling.annotation
#Configuration
#EnableScheduling
you can set it with a fixedDelay
#Scheduled(fixedDelay = 1000)
with initialDelay also:
#Scheduled(fixedDelay = 1000, initialDelay = 1000)
or with a fixedRate (when each execution of the task is independent)
#Scheduled(fixedRate = 1000)
you can also create it on runtime using
org.springframework.scheduling.annotation.SchedulingConfigurer
public class SchedulerContextconfig implements SchedulingConfigurer
#Override
public void configureTasks(ScheduledTaskRegistrar register) {
register.addCronTask(Runnable task, String expression)
}

Resources