How to parameterize @Scheduled(fixedDelay) with Spring 3.0 expression language?
Asked Answered
Q

6

153

When using the Spring 3.0 capability to annotate a scheduled task, I would like to set the fixedDelay as parameter from my configuration file, instead of hard-wiring it into my task class, like currently...

@Scheduled(fixedDelay = 5000)
public void readLog() {
        ...
}

Unfortunately it seems that with the means of the Spring Expression Language (SpEL) @Value returns a String object which in turn is not able to be auto-boxed to a long value as required by the fixedDelay parameter.

Quart answered 8/4, 2010 at 9:19 Comment(0)
M
26

I guess the @Scheduled annotation is out of question. So maybe a solution for you would be to use task-scheduled XML configuration. Let's consider this example (copied from Spring doc):

<task:scheduled-tasks scheduler="myScheduler">
    <task:scheduled ref="someObject" method="readLog" 
               fixed-rate="#{YourConfigurationBean.stringValue}"/>
</task:scheduled-tasks>

... or if the cast from String to Long didn't work, something like this would:

<task:scheduled-tasks scheduler="myScheduler">
    <task:scheduled ref="someObject" method="readLog"
            fixed-rate="#{T(java.lang.Long).valueOf(YourConfigurationBean.stringValue)}"/>
</task:scheduled-tasks>

Again, I haven't tried any of these setups, but I hope it might help you a bit.

Mcmillan answered 8/4, 2010 at 19:8 Comment(3)
Thanks, the XML configuration did the trick. I am bit surprised that the annotation seems so bound to string values, anyways, I go with the old-school way ;-)Quart
Is there any Java equivalent for above config?Savick
@Grzegorz Oledzki what will be the value of "someObject" under <task:scheduled > tag. If a controller have more than one method that needs fixed delay and initial delay then how will that be handled?Contain
B
488

Spring v3.2.2 has added String parameters to the original 3 long parameters to handle this. fixedDelayString, fixedRateString and initialDelayString are now available too.

@Scheduled(fixedDelayString = "${my.fixed.delay.prop}")
public void readLog() {
        ...
}
Berti answered 9/5, 2013 at 13:51 Comment(3)
@Avi This answer comes three years after the OP's question. At the time of the question (and accepted answer) this feature didn't exist.Dunleavy
@medveshonok117 and? it is still the most correct answer now.Saraband
In Kotlin you need to escape the $ in the String: "\${my.fixed.delay.prop}"Lackaday
B
54

You can use the @Scheduled annotation, but together with the cron parameter only:

@Scheduled(cron = "${yourConfiguration.cronExpression}")

Your 5 seconds interval could be expressed as "*/5 * * * * *". However as I understand you cannot provide less than 1 second precision.

Bauman answered 19/1, 2012 at 13:28 Comment(1)
The cron expression that you have shown is equivalent to fixedRate, which is different to fixedDelayDiploid
M
26

I guess the @Scheduled annotation is out of question. So maybe a solution for you would be to use task-scheduled XML configuration. Let's consider this example (copied from Spring doc):

<task:scheduled-tasks scheduler="myScheduler">
    <task:scheduled ref="someObject" method="readLog" 
               fixed-rate="#{YourConfigurationBean.stringValue}"/>
</task:scheduled-tasks>

... or if the cast from String to Long didn't work, something like this would:

<task:scheduled-tasks scheduler="myScheduler">
    <task:scheduled ref="someObject" method="readLog"
            fixed-rate="#{T(java.lang.Long).valueOf(YourConfigurationBean.stringValue)}"/>
</task:scheduled-tasks>

Again, I haven't tried any of these setups, but I hope it might help you a bit.

Mcmillan answered 8/4, 2010 at 19:8 Comment(3)
Thanks, the XML configuration did the trick. I am bit surprised that the annotation seems so bound to string values, anyways, I go with the old-school way ;-)Quart
Is there any Java equivalent for above config?Savick
@Grzegorz Oledzki what will be the value of "someObject" under <task:scheduled > tag. If a controller have more than one method that needs fixed delay and initial delay then how will that be handled?Contain
L
16

In Spring Boot 2, we can use Spring Expression Language (SpPL) for @Scheduled annotation properties:

@Scheduled(fixedRateString = "${fixed-rate.in.milliseconds}")
public void fixedRate() {
    // do something here
}

@Scheduled(fixedDelayString = "${fixed-delay.in.milliseconds}")
public void fixedDelay() {
    // do something here
}

@Scheduled(cron = "${cron.expression}")
public void cronExpression() {
    // do something here
}

The application.properties file will look like this:

fixed-rate.in.milliseconds=5000
fixed-delay.in.milliseconds=4000
cron.expression=0 15 5 * * FRI

That's it. Here is an article that explains task scheduling in detail.

Leucite answered 20/8, 2019 at 13:0 Comment(0)
M
1

I guess you can convert the value yourself by defining a bean. I haven't tried that, but I guess the approach similar to the following might be useful for you:

<bean id="FixedDelayLongValue" class="java.lang.Long"
      factory-method="valueOf">
    <constructor-arg value="#{YourConfigurationBean.stringValue}"/>
</bean>

where:

<bean id="YourConfigurationBean" class="...">
         <property name="stringValue" value="5000"/>
</bean>
Mcmillan answered 8/4, 2010 at 9:22 Comment(3)
Thanks, that sounds like one way, but to be honest I was hoping for a more elegant ("springish") solution :-)Quart
Unfortunately this will not work, since the @Scheduled annotation attribute fixedDelay requires a (long) constant to be assigned.Quart
Ah, that's right. So I guess you can't do it with the @Scheduled annotation then.Mcmillan
T
0

In case of delay configured as Duration, e.g. 5s, there are not pretty, but working solution from issues: support flexible duration parsing in placeholders

@Scheduled(fixedRateString = 
   "#{T(org.springframework.boot.convert.DurationStyle).detectAndParse('${app.update-cache}')}")

I do not understand, why issue is closed and Duration is not realized yet
BTW: I've tried, but without success, a little more pretty:

@Scheduled(fixedRateString = "'PT'+'${app.update-cache}'") and
@Scheduled(fixedRateString = "'PT'.concat('${app.update-cache}')
Thymus answered 27/1 at 21:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.