Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
676 views
in Technique[技术] by (71.8m points)

java - Spring-Boot one @Scheduled task using multiple cron expressions from yaml file

I like to have an implementation of one @Scheduled job using different configuration properties of .ymlfile.

Means in my yaml file I describe the cron expression as a list:

job:
  schedules:
  - 10 * * * * *
  - 20 * * * * *

I read those values out using Configuration and created a @Bean named scheduled:

@Configuration
@ConfigurationProperties(prefix="job", locations = "classpath:cronjob.yml")
public class CronConfig {

    private List<String> schedules;

    @Bean
    public List<String> schedules() {
        return this.schedules;
    }

    public List<String> getSchedules() {
        return schedules;
    }

    public void setSchedules(List<String> schedules) {
        this.schedules = schedules;
    }
}

In my Job class I want to start the execution of one method but for both of the schedules in my configuration.

 @Scheduled(cron = "#{@schedules}")
 public String execute() {
     System.out.println(converterService.test());
     return "success";
 }

With this solution the application creates an error: (more or less clear)

Encountered invalid @Scheduled method 'execute': Cron expression must consist of 6 fields (found 12 in "[10 * * * * *, 20 * * * * *]")

Is there a way to configure the same scheduled job method with multiple declarations of cron expressions?


EDIT 1

After some try I just used a second annotation on the executer method.

@Scheduled(cron = "#{@schedules[0]}")
@Scheduled(cron = "#{@schedules[1]}")
public String execute() {
    System.out.println(converterService.test());
    return "success";
}

This solution works but is not really dynamic. Is there also a way to make this dynamic?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

(edit since I found a way to perform this)

You can actually do this. Below I'm showcasing a working example:

cronjob.yaml

job:
  schedules:
  - 10 * * * * *
  - 20 * * * * *

the actual task to perform MyTask:

package hello;

import org.springframework.stereotype.Component;

@Component
public class MyTask implements Runnable {

    @Override
    public void run() {
        //complicated stuff
    }
}

Your CronConfig as is:

package hello;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

    @Configuration
    @ConfigurationProperties(prefix="job", locations = "classpath:cronjob.yml")
    public class CronConfig {

        private List<String> schedules;

        @Bean
        public List<String> schedules() {
            return this.schedules;
        }

        public List<String> getSchedules() {
            return schedules;
        }

        public void setSchedules(List<String> schedules) {
            this.schedules = schedules;
        }
    }

The ScheduledTask bean that is responsible to schedule all crons:

package hello;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTasks {

    @Autowired
    private TaskScheduler taskScheduler;

    @Autowired
    private CronConfig cronConfig;

    @Autowired
    private MyTask myTask;

    private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);

    public void scheduleAllCrons() {

        cronConfig.getSchedules().forEach( cron -> taskScheduler.schedule(myTask, new CronTrigger(cron)) );
    }
}

The context/main class Application:

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;

@SpringBootApplication
@EnableScheduling
@EnableAsync
public class Application {

    @Bean
    public TaskScheduler taskScheduler() {
        return new ConcurrentTaskScheduler();
    }


    public static void main(String[] args) throws Exception {
        ApplicationContext ctx = SpringApplication.run(Application.class);

        ScheduledTasks scheduledTasks = ctx.getBean(ScheduledTasks.class);

        scheduledTasks.scheduleAllCrons();
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...