I have already define Scheduler in my spring boot project. Then I have to implement task scheduler which run thread pool. After I have added my scheduler task won't triggered. Even test case didn't run.
Scheduler Config Class
#Configuration
#EnableScheduling
public class SchedulerConfig {
}
Thread pool config class
#Configuration
#EnableAsync
public class AsyncConfig {
private ThreadPoolTaskExecutor executor;
#Bean
public TaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
executor.setMaxPoolSize(500);
executor.initialize();
return executor;
}
}
#Async("threadPoolTaskExecutor")
public void smsProcessor(List<CampaignSchedulerData> campaignSchedulerDataList, int tenantId) throws InterruptedException {
// file reader from AWS and send message accordingly
}
Scheduler task
#Scheduled(cron = "${cron-expression.file-write}")
public void fileWriteScheduler() {
LocalDateTime startDateTime = LocalDateTime.now();
log.info("Run file Write Scheduler. Start time is :: {} ",
DateTimeUtil.DATE_TIME_FORMATTER.print(startDateTime));
//add config scheduler time
schedulerService.processFileWriteScheduler(startDateTime.minusMillis(file_write_SchedulerWaitingTime));
LocalDateTime endDateTime = LocalDateTime.now();
log.info("Run file Write Scheduler. ", "End time is :: {} ",
DateTimeUtil.DATE_TIME_FORMATTER.print(endDateTime), ". Time taken :: {} ", Period.fieldDifference(startDateTime, endDateTime));
}
I have tried to implement task scheduler then ApplicationSpringBoot class won't run.
#SpringBootApplication
#EnableFeignClients
//Enable Annotations
public class BusinessTemplateApplication {
}
I figured this out.
When I add the task scheduler to the SchedulerConfig class it will resolved
#Configuration
#EnableScheduling
public class SchedulerConfig {
#Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(500);
threadPoolTaskScheduler.setThreadNamePrefix("ThreadPoolTaskScheduler");
return threadPoolTaskScheduler;
}
}
Related
I have created a Spring Boot application wherein main class I am creating a scheduler object.
prop.put("quartz.scheduler.instanceName", "ServerScheduler");
prop.put("org.quartz.scheduler.instanceId", "AUTO");
prop.put("org.quartz.scheduler.skipUpdateCheck", "true");
prop.put("org.quartz.scheduler.instanceId", "CLUSTERED");
prop.put("org.quartz.scheduler.jobFactory.class", "org.quartz.simpl.SimpleJobFactory");
prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate");
prop.put("org.quartz.jobStore.dataSource", "quartzDataSource");
prop.put("org.quartz.jobStore.tablePrefix", "H1585.QRTZ_");
prop.put("org.quartz.jobStore.isClustered", "false");
prop.put("org.quartz.scheduler.misfirePolicy", "doNothing");
prop.put("org.quartz.dataSource.quartzDataSource.driver", "com.ibm.db2.jcc.DB2Driver");
prop.put("org.quartz.dataSource.quartzDataSource.URL", url);
prop.put("org.quartz.dataSource.quartzDataSource.user", user);
prop.put("org.quartz.dataSource.quartzDataSource.password", passwrd);
prop.put("org.quartz.dataSource.quartzDataSource.maxConnections", "2");
SpringApplication.run(SchedulerApplication.class, args);
try {
SchedulerFactory stdSchedulerFactory = new StdSchedulerFactory(prop);
Scheduler scheduler = stdSchedulerFactory.getScheduler();
scheduler.start();
I want to use the same scheduler object in my service class to trigger the job. The one which I am getting using below code is not working showing different instance id.
scheduler = StdSchedulerFactory.getDefaultScheduler();
How can I solve this?
you can create a singleton Scheduler, and autowired in your service class
#SpringBootApplication
public class SchedulerApplication {
public static void main(final String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Bean
public Scheduler scheduler() {
//create props as you above code
SchedulerFactory stdSchedulerFactory = new StdSchedulerFactory(prop);
Scheduler scheduler = stdSchedulerFactory.getScheduler();
scheduler.start();
return scheduler;
}
}
then you can use in your service class
#Service
public class YourServiceClass {
#Autowired
private Scheduler scheduler;
}
I have configured two different thread pools, one for #Scheduled and other for #Async. However, I notice that the thread-pool for #Async is not being used.
Here is the Scheduler configuration
#Configuration
#EnableScheduling
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-sched-pool-");
threadPoolTaskScheduler.initialize();
scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
}
}
Here is the Configuration for Async
#Configuration
#EnableAsync
public class AppConfig {
#Bean(name = "asyncTaskExecutor")
public TaskExecutor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(15);
executor.setMaxPoolSize(15);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("my-async-pool-");
executor.initialize();
return executor;
}
}
Here is how I invoke them
#Scheduled(fixedRateString = "2000" )
public void schedule() {
log.debug("here is the message from schedule");
asyncMethod();
}
#Async("asyncTaskExecutor")
public void asyncMethod(){
log.info("here is the message from async");
}
Here are the logs
{"thread":"my-sched-pool-1","level":"DEBUG","description":"here is the message from schedule"}
{"thread":"my-sched-pool-1","level":"INFO","description":"here is the message from async"}
As you can notice, both logs are having same pool of that scheduler. but I expect to see the second one to come from async
If you call #Async methods from the same class they are declared you are effectively bypassing Spring's proxy mechanism and that is why your example is not working. Try calling the method from a separate class annotated with #Service or any of the other #Component types.
#Service
SomeScheduledClass {
private final SomeAsyncClass someAsyncClass;
public SomeScheduledClass(SomeAsyncClass someAsyncClass) {
this.someAsyncClass = someAsyncClass;
}
#Scheduled(fixedRateString = "2000" )
public void schedule() {
log.debug("here is the message from schedule");
someAsyncClass.asyncMethod();
}
}
#Service
SomeAsyncClass {
#Async("asyncTaskExecutor")
public void asyncMethod(){
log.info("here is the message from async");
}
}
In my spring boot app, i am creating scheduled task programatically e.g
#Configuration
#EnableScheduling
public class AppConfig implements SchedulingConfigurer {
#Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskScheduler());
//following loop will get executed according to requirement for now //just looping 0-9
for(int i=0;i<10;i++){
MyRunnable myRunnable=new MyRunnable();
myRunnable.setID(i);
taskRegistrar.addTriggerTask(myRunnable,new CronTrigger("0 0/15 * * * *"));
}
}
#Bean(destroyMethod="shutdown")
public Executor taskScheduler() {
return Executors.newScheduledThreadPool(42);
}
#Bean
public MyTask myTask() {
return new MyTask();
}
}
I need some way to reschedule above task on the fly,can some one help me to complete above work? i would prefer rescheduling task by ID like myRunnable.getID().
Any help would be highly appreciated?
i have tried following in my Controller
#Autowired
private ScheduledTaskRegistrar scheduledTaskRegistrar;
But it is not injecting in controller
This question already has an answer here:
Spring 3.x - #Async methods not called concurrently by task executor
(1 answer)
Closed 7 years ago.
I have a long running service method which I'm starting with a rest call from the controller.
Service:
#Service
public class TestServiceImpl implements TestService {
#Override
public void doSomething() {
System.out.println("1: " + DateTime.now());
runLongTask();
System.out.println("2: " + DateTime.now());
}
#Async
private runLongTask() {
System.out.println("Test");
Thread.sleep(10000);
System.out.println("3: "+ DateTime.now());
}
}
In my Application.java I have
private int poolSize = 10;
private int queueCapacity = 10;
#Bean(name="taskExecutor")
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setMaxPoolSize(this.poolSize);
taskExecutor.setQueueCapacity(this.queueCapacity);
taskExecutor.afterPropertiesSet();
return new ThreadPoolTaskExecutor();
}
And of course I have the #EnableAsync Annotation at my Application.java class
So I would Expect that the output is something like that:
1: 2015-10-23 11:20:00
2: 2015-10-23 11:20:01
Test
3: 2015-10-23 11:20:11
you need to call method from different class to use annotations like #Async or #Transactional. Spring do this stuff by wrapping annotated methods by proxy. In case when you call method from the same class then it has no effect.
According to the documentation you need to implement the AsyncConfigurer interface in your Configuration class (in this case I assume is your Application instance) to override the SimpleAsyncTaskExecutor.
A full example is also shown in the documentation:
#Configuration
#EnableAsync
public class AppConfig implements AsyncConfigurer {
#Bean
public MyAsyncBean asyncBean() {
return new MyAsyncBean();
}
#Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(7);
executor.setMaxPoolSize(42);
executor.setQueueCapacity(11);
executor.setThreadNamePrefix("MyExecutor-");
executor.initialize();
return executor;
}
#Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return MyAsyncUncaughtExceptionHandler();
}
}
HTH,
Jose Luis
I have an #Scheduled task which send data to a client every sec throught a websocket.
My need is to start running my scheduled task only when the client ask for it.
Instead of, my task starts when my server starts. it's not the behavior i want.
currently, I have a bean of my scheduled task which is declared in my SchedulingConfigurer :
#Configuration
#EnableScheduling
public class SchedulingConfigurer implements org.springframework.scheduling.annotation.SchedulingConfigurer {
#Bean
public ThreadPoolTaskScheduler taskScheduler() {
return new ThreadPoolTaskScheduler();
}
#Bean
public ScheduledTask scheduledTask() {
return new ScheduledTask();
}
#Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setTaskScheduler(taskScheduler());
}
}
Here is my spring controller code :
#MessageMapping("/hello")
public void greeting() throws Exception {
//How do I start my scheduled task here ?
}
Maybe isn't possible to do that with #Scheduled annotation and i have to use the TaskScheduler interface ?
remove #Scheduled declaration from ScheduledTask class
implements Runnable interface instead of
#Component
//#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ScheduledTask implements Runnable {
private static final Logger log = LoggerFactory.getLogger(ScheduledTask.class);
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
public void doWork() {
printMessage();
// TODO real work
}
private void printMessage() {
log.info("time to work: {}", dateFormat.format(new Date()));
}
#Override
public void run() {
doWork();
}
}
schedule Your task in controller area like this
#Controller
public class ScheduledTaskController {
#Autowired
private TaskScheduler taskScheduler;
#Autowired
private ScheduledTask scheduledTask;
#RequestMapping(value = "/task/run", method = RequestMethod.GET)
public String runTask() {
// start to run task every 5 sec.
taskScheduler.schedule(scheduledTask, new CronTrigger("0/5 * * * * ?"));
// ok, redirect
return "redirect:/task";
}
}
#Schedule is the declarative way, so not the point you're trying to achieve here.
You could create a Bean using one of the TaskScheduler implementations, such as ThreadPoolTaskScheduler and inject that bean in your application.
It has all the necessary methods to dynamically schedule tasks.