I am trying to run this job in spring but i am getting an error
My intention is to run the job last Friday of every month
#EnableScheduling
#Service
public class TestSchedular {
#Scheduled(cron= "0 0 0 ? * 6L")
public void schedular() {
System.out.println("Cron Job");
}
Error:
Caused by: java.lang.IllegalStateException: Encountered invalid #Scheduled method 'schedular': For input string: "6L"
What is wrong with this code?
Your cron expression ("0 0 0 ? * 6L") is invalid.
Spring's CronSequenceGenerator class has a method isValidExpression(String expression) which takes the cron expression and returns a boolean.
You could use that to check your Cron expression.
Related
I am trying to schedule my rest service(with GET method) using
#Scheduled(cron = xyzzy.getTimeSchedule())
The schedule details are expected to be obtained from application properties from cloud during the application start up. however I get "The value for Annotation attribute Scheduled.cron must be a constant expression" compile time error. Please suggest. Also what might be the underlying issue like with the Spring annotation and the properties being available during the time application start up. Please guide or direct me to understand.TIA.
Using #Scheduled annotation you cannot provide a method for cron-expression which comes from the cloud. As java annotation needs constant-expression, which is a variable whose value cannot change once it has been assigned. For that, you need to use final keyword.
public static final String TIME_SCHEDULE = "0 0/30 8-10 * * *";
Then use that constant expression in your scheduler method,
#Scheduled(cron = TIME_SCHEDULE)
In your case, you should go for #TaskScheduler (from doc)
Task scheduler interface that abstracts the scheduling of Runnables based on different kinds of triggers.
This interface is separate from SchedulingTaskExecutor since it usually represents for a different kind of backend, i.e. a thread pool with different characteristics and capabilities. Implementations may implement both interfaces if they can handle both kinds of execution characteristics.
Replacing #Scheduled annotation with #TaskScheduler
First, autowire TaskScheduler and make sure that you annotated your main class with #EnableScheduling annotation to provide bean for TaskScheduler.
#Autowired
private TaskScheduler scheduler;
Now you need to schedule providing Runnable and CronTrigger arguments. It schedules the given Runnable, invoking it whenever the trigger indicates a next execution time.
That means you need to wrap your logic(currently this is the code from your #Schduled method body) into Runnable instance. And your xyzzy.getTimeSchedule() should be provided to CronTrigger constructor.
Runnable runnableTask = () -> {
//call REST API here
};
scheduler.schedule(runnableTask, new CronTrigger(xyzzy.getTimeSchedule());
Now you get rid of "The value for Annotation attribute Scheduled.cron must be a constant expression"
Finally this is what worked for me.
I have my property stored as key : value pair over the cloud.like so..
xyz.Schedule = */5 * * * * ;
public Class testController {
#Autowired
private Type type;
#Scheduled(cron = "${type.getSchedule()}")
#GetMapping(path = "/", produces = "application/json")
public void getmethod() { blah blah } }
I ran my application successfully and was being able to populate the property configured over cloud at the start of application, and was able to get response for my api as well.
Things I tried:
As suggested by Shekhar Rai in this discussion chain, declaring it as final variable, but was unable to access it in my method.
tried wrapping the method as a runnable task, couldn't do so.
arrived at: #Scheduled.cron always expects a constant parameter(like a string), but get() is dynamic , therefore wrapped it as a constant parameter.
#ManagedConfiguration
private ConfigClass configClass;
#bean
public String getSchedulerValue() {
return configClass.getSchedule();}
#Scheduled(cron="#{getSchedulerValue}")
I've got an Async method which is scheduled to run once a day:
#Component
public class MyClass {
//myCronProperty set to "0 25 20 * * *" in application.properties
#Scheduled(cron="{myCronProperty}")
#Async
#Override
public void doDailyTask() {
//Do work here
}
}
Is there a way of triggering doDailyTask() for testing purposes when the application is already running, perhaps by doing something clever with Groovy and reflection?
I figure I can always tweak the cron property to 1 minute in the future in my application.properties file, and then restart the application - but just wondered if there was a smarter method?
You should be able to simply inject the component into another class, for example a #RestController, and invoke the doDailyTask() method on it there.
package com.test.cron;
#Service
public class CronJob {
protected static final Logger logger = Logger.getLogger(CronJob.class);
#Scheduled(cron="0 0 23 * * *")
public void demoServiceMethod()
{
logger.debug("Cron job started.");
}
}
Cron excution time will be often changed.
I have to exchange '#Scheduled' annotation to java code.
You can externalize this cron value into a properties file.
#Scheduled(cron="${schedularTime}")
and in your properties file ( example: application-dev.properties)
schedularTime=0 0/2 * * * ?
Old thread, but there is no real answer to the question.
Here is a way to schedule jobs without any annotations.
The example is in Kotlin, but works the same way in java.
#Component
class CliRunner(
private val scheduler: ThreadPoolTaskScheduler,
private val scheduledService: ScheduledService
) : CommandLineRunner {
override fun run(vararg args: String) {
scheduler.scheduleAtFixedRate(scheduledService::run, 10_000)
}
}
Inject ThreadPoolTaskScheduler and whatever you want to schedule, and call any of the scheduling methods on the scheduler.
My example schedules the run method to be executed every 10 seconds.
You could use a database for the configuration of schedule, Quartz had a capability to save its job meta data in a datasource.
Somebody had implemented something like this here.
https://github.com/davidkiss/spring-boot-quartz-demo
Hello i working on a cron job and would like to schedule the task to run once every two weeks on a Monday morning using #schedule in spring can anyone help me out here?
You should check out the getting started examples in the spring.io website:
Scheduling Tasks
For your use case you'll be using the scheduled annotation with a cron expression:
#Scheduled(cron=". . .")
This uses the CronSequenceGenerator.
As the other answer mentioned you just have to add the #Scheduled annotation. however if using spring boot dont forget to add this anotation #EnableScheduling in the main class of your app
#EnableScheduling
#EnableAutoConfiguration
public class MyApplication {
Hope it helps
If you use not springboot but spring framework, you can configure scheduling job like below.
#EnableScheduling
#Configuration
public class SchedulingConfig {
// ...
}
And use like this.
private static final int TEN_MINUTES = 60 * 10 * 1000;
#Scheduled(fixedRate = TEN_MINUTES)
public void doSomething() {
// ...
}
Regarding the cron expression for every two weeks, here're some discussion.
It seems not very convenient to use cron expression to set two weeks schedule. Instead, you can use cron expression to set weekly tasks, and use a boolean variable to flip the boolean value:
boolean flag;
// run the method at 8:00 AM every Monday
#Scheduled(cron="0 0 8 * * MON")
public void schedulingTask() {
// run the actual task only if flag is true
if (flag) {
// handle the biweekly task
}
// flip the flag
flag = !flag;
}
I want to schedule a method call in Spring MVC to run after every two hours. This I can easily do via Spring 3.0 Time Scheduler. However, I want to kick the execution off only at a specific time of the day. That is, the method should only be invoked every 2 hours starting at a particular time.
For example - I want the method to run every 2 hours starting 6 AM.
The TimeScheduler interface has a scheduleAtFixedRate method which is overloaded to use startTime Date argument. I am not really sure how to use this.
Any idea how this can be achieved ?
You could take a look at the TaskScheduler interface. It provides a method scheduleAtFixedRate(Runnable task, Date startTime, long period) which returns a ScheduledFuture. You can use this with some simple Spring configuration:
<task:scheduler id="scheduler" pool-size="10"/>
This will create an instance of ThreadPoolTaskScheduler which implements TaskScheduler. Wire this bad boy into the class to call your specific method:
public class MyClass {
#Autowired
private TaskScheduler scheduler;
public void init() {
scheduler.scheduleAtFixedRate(new Runnable() {
public void run() {
myMethod();
}
}, new Date(), 1000 * 60 * 60 * 2); //This will start now and run every two hours
}
public void myMethod() {
// the method you want to invoke
}
}
I would take a look at Spring's support for Task Execution and Scheduling. Specifically check out the #Scheduled annotation (with which you can specify a schedule based on a cron expression):
#Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() {
// something that should execute on weekdays only
}