Noam
Noam

Reputation: 3155

How to use @Scheduled(cron) with SpEL in spring?

I have a method that I want spring to schedule - for that matter I'm using the @Scheduled annotation - and to be more exact, I'm using a cron expression. My cron expression is in a property file that is called scheduler.properties. When I'm using it as a placeholder @Scheduled(cron="${cron}") - everything works great; but I want to use SpEL ( @Scheduled(cron="#{scheduler['cron']}") ) , and it does't work - throws the following exception:java.lang.IllegalArgumentException: cron expression must consist of 6 fields (found 1 in #{scheduler['cron']})

What am I doing wrong here?

EDIT: Here is my cron expression from the properties file: cron=0 0/1 * * * ?

Here is the stack trace that I get: java.lang.IllegalArgumentException: cron expression must consist of 6 fields (found 1 in #{scheduler['cron']}) at org.springframework.scheduling.support.CronSequenceGenerator.parse(CronSequenceGenerator.java:233) at org.springframework.scheduling.support.CronSequenceGenerator.<init>(CronSequenceGenerator.java:81) at org.springframework.scheduling.support.CronTrigger.<init>(CronTrigger.java:54) at org.springframework.scheduling.support.CronTrigger.<init>(CronTrigger.java:44) at org.springframework.scheduling.config.ScheduledTaskRegistrar.afterPropertiesSet(ScheduledTaskRegistrar.java:188) at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:209) at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:1) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:97) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:324) at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:929) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:467) at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:384) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4723) at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5226) at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5221) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) at java.util.concurrent.FutureTask.run(FutureTask.java:166) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) at java.lang.Thread.run(Thread.java:722)

SECOND EDIT: It seems that spring is trying to parse the following string as the cron experssion "#{scheduler['cron']}" insraed of the actual cron expression itself.

Upvotes: 5

Views: 16248

Answers (4)

user1842915
user1842915

Reputation: 61

It works. I spent days figuring out... but this indeed works.

  1. You should set environment variable like you do for JAVA_HOME etc.
  2. Close your IDE.

export cron_scheduler_expression="0 19 21 * * *"

Then restart your IDE, Eclipse or NetBeans whatever you are using.

@Scheduled(cron = "${cron_scheduler_expression}")
public void runSchedulerTask(){

}

Upvotes: 0

Ashu
Ashu

Reputation: 1733

I had a similar issue and resolved it by reading property file with context:property-placeholder

<util:properties id="applicationProps" location="/WEB-INF/classes/properties/application.properties" /> **<context:property-placeholder properties-ref="applicationProps" />**

Hope it helps someone!!

Upvotes: 1

Kul Bhushan Prasad
Kul Bhushan Prasad

Reputation: 879

Always specify like this in property file: Notice the space in between frequency.

run refresh job every day a 9am

job.cron.rate=0 0 9 * * *

Example patterns:

* "0 0 * * * *" = the top of every hour of every day.
* "*/10 * * * * *" = every ten seconds.
* "0 0 8-10 * * *" = 8, 9 and 10 o'clock of every day.
* "0 0/30 8-10 * * *" = 8:00, 8:30, 9:00, 9:30 and 10 o'clock every day.
* "0 0 9-17 * * MON-FRI" = on the hour nine-to-five weekdays
* "0 0 0 25 12 ?" = every Christmas Day at midnight

Use it like this in Code:

@Scheduled(cron = "${job.cron.rate}")    
public void perform() throws InterruptedException {
}

Upvotes: 1

Rob Kielty
Rob Kielty

Reputation: 8172

According to the error message, the value of the cron expression in your properties file is incorrect.

It does not conform to the expected syntax.

The value should contain six fields and look something like this.

* 10 * * * *

Here's the code that throws this exception

/**
 * Parse the given pattern expression.
 */
private void parse(String expression) throws IllegalArgumentException {
    String[] fields = StringUtils.tokenizeToStringArray(expression, " ");
    if (fields.length != 6) {
        throw new IllegalArgumentException(String.format(""
                + "cron expression must consist of 6 fields (found %d in %s)", fields.length, expression));
    }

It may not be possible to externalize cron configuration using spEL in an Annotation.

The alternatives are to use XML or use the cron expression.

http://forum.springsource.org/showthread.php?91203-Scheduled-and-externalization-of-configuration-for-fixedDelay-and-fixedRate-problem

Upvotes: 3

Related Questions