Reputation: 37014
I have following annotation in my code
@Scheduled(fixedDelayString = "${app.delay}")
At this case I have to have properties like this
app.delay=10000 #10 sec
Propery file looks unreadable because I have calculate value to miliseconds.
Is there way to pass value like 5m or 30s there ?
Upvotes: 12
Views: 5819
Reputation: 44757
As far as I know, you can't do it directly. However, Spring boot configuration properties do support automatic conversion of parameters like 15s
and 5m
to Duration
.
This means you could create a @ConfigurationProperties
class like this:
@ConfigurationProperties("app")
public class AppProperties {
private Duration delay;
// Setter + Getter
}
Additionally, since you can use bean references with Spring's Expression Language within the @Scheduled
annotation, you can do something like this:
@Scheduled(fixedDelayString = "#{@'app-com.xyz.my.pkg.AppProperties'.delay}")
public void schedule() {
log.info("Scheduled");
}
Note: When you use
@EnableConfigurationProperties
or@ConfigurationPropertiesScan
, the configurationproperties beans are registered with the name<prefix>-<fully qualified classname>
. So in the example above, I'm assuming that theAppProperties
class is located in a package calledcom.xyz.my.pkg
.If you don't like this, you can also use the
@Component("beanName")
annotation on top of theAppProperties
class to give it a different bean name.
Alternatively, you can programmatically add a task to the TaskScheduler
. The benefit of that is that you have more compile-time safety.
@Bean
public ScheduledFuture<?> schedule(TaskScheduler scheduler, AppProperties properties) {
return scheduler.scheduleWithFixedDelay(() -> log.info("Scheduled"), properties.getDelay());
}
Upvotes: 14
Reputation: 103
I understand this is a fairly old question but maybe it's worth to provide an updated (as of 2023) answer.
There are actually a couple of ways to do this.
I will assume the property is defined as a "natural" time string, i.e. app.delay=20s
instead of app.delay=PT20S
, but both cases would work.
If the property app.delay
is not part of of @ConfigurationProperties
, you can use the following expression:
@Scheduled(fixedDelayString = "#{T(org.springframework.boot.convert.ApplicationConversionService).getSharedInstance().convert('${app.delay}', T(java.time.Duration)).toMillis()}")
If you defined the property app.delay
as part of "normal" (i.e. not a @Component
) @ConfigurationProperties
, like so:
@ConfigurationProperties("app")
public class AppProperties {
private Duration delay;
// Getters + Setters
}
Then, assuming this class is in package com.package
, you can use
@Scheduled(fixedDelayString = "#{@'app-com.package.AppProperties'.getDelay().toMillis()}")
Because this is how naming of the Configuration Properties beans works in Spring Boot (see reference doc).
@Component
)(which is the original answer by @g00glen00b)
If you defined the property app.delay
as part of @ConfigurationProperties
, which are also a @Component
like so:
@Component
@ConfigurationProperties("app")
public class AppProperties {
private Duration delay;
// Getters + Setters
}
Then you can refer to the bean name as follows
@Scheduled(fixedDelayString = "#{@appProperties.getDelay().toMillis()}")
Upvotes: 4
Reputation: 5517
I'm using this code and it works fine:
@Scheduled(fixedDelayString = "PT10S")
Upvotes: 4
Reputation: 15028
You can just adjust your annotation to use a SpEL multiplication.
@Scheduled(fixedDelayString = "#{${app.delay} * 1000}")
Upvotes: 3
Reputation: 692271
Assuming you're using a recent enough version of Spring, you can use any String that can be parsed to a java.time.Duration
. In your case:
PT10S
Upvotes: 5