Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I add context in @Scheduled?

This is my code :

 @Scheduled(cron = "30 3 * * * *")
    public void myCron() {
        //we don't care what we do here
    }

I want to know if it is possible to add a tracking id (or other information) on my @Scheduled automatically.

The id will be different each time @Scheduled is triggered.

I want to do this to avoid to duplicate code like :

@Scheduled(cron = "10 3 * * * *")
public void myCron() {
    MDC.put("myId", UUID.randomUUID().toString());
    //we don't care what we do here
}
@Scheduled(cron = "30 3 * * * *")
public void mySecondCron() {
    MDC.put("myId", UUID.randomUUID().toString());
    //we don't care what we do here
}

I tired to implements SchedulingConfigurer but SchedulingConfigurer#configureTasks is too late too add behavior on taks because the task (runnable) is already created

Thanks

like image 417
ahammani Avatar asked Dec 21 '17 09:12

ahammani


People also ask

What is @scheduled in spring?

Spring Core. Spring provides excellent support for both task scheduling and asynchronous method execution based on cron expression using @Scheduled annotation. The @Scheduled annotation can be added to a method along with trigger metadata.

What is @scheduled in spring boot?

The @EnableScheduling annotation is used to enable the scheduler for your application. This annotation should be added into the main Spring Boot application class file. @SpringBootApplication @EnableScheduling public class DemoApplication { public static void main(String[] args) { SpringApplication.

What is fixed delay in spring scheduler?

Schedule a Task at Fixed Delay In this case, the duration between the end of the last execution and the start of the next execution is fixed. The task always waits until the previous one is finished. This option should be used when it's mandatory that the previous execution is completed before running again.


1 Answers

You can try to implement custom TaskScheduler and register it in SchedulingConfigurer.configureTasks. ConcurrentTaskScheduler can be considered as an example. Unfortunately this class isn't well-designed for inheritance, otherwise decorateTask method will be protected. So you need to override all methods to add one additional Runnable decorator with your logic. Something like this one :

@Configuration
@EnableScheduling
public class ScheduledConfig implements SchedulingConfigurer {

    public static class MyTaskScheduler extends ConcurrentTaskScheduler {

        public MyTaskScheduler() {
        }

        public MyTaskScheduler(ScheduledExecutorService scheduledExecutor) {
            super(scheduledExecutor);
        }

        public MyTaskScheduler(Executor concurrentExecutor, ScheduledExecutorService scheduledExecutor) {
            super(concurrentExecutor, scheduledExecutor);
        }

        // TODO override other methods

        @Override
        public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
            return super.schedule(decorateTask(task), trigger);
        }

        private Runnable decorateTask(Runnable task) {
            // not 100% sure about safety of this cast
            return new MyRunnable((ScheduledMethodRunnable) task);
        }

        private static class MyRunnable implements Runnable {

            private final ScheduledMethodRunnable runnable;
            private final AtomicLong counter = new AtomicLong();

            public MyRunnable(ScheduledMethodRunnable runnable) {
                this.runnable = runnable;
            }

            @Override
            public void run() {
                System.out.println(runnable.getMethod().toGenericString() + " " + counter.incrementAndGet());
                runnable.run();
            }
        }
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        TaskScheduler taskScheduler = new MyTaskScheduler(Executors.newScheduledThreadPool(10));
        taskRegistrar.setTaskScheduler(taskScheduler);
    }

    @Scheduled(cron = "0/1 * * * * *")
    public void test() {
        System.out.println("Running task in thread " + Thread.currentThread().getId());
    }
}
like image 176
Nikita Gorbachevski Avatar answered Oct 13 '22 22:10

Nikita Gorbachevski