3

I have a final config-class like this:

@Value // <- lombok-annotation
@ConstructorBinding
@ConfigurationProperties("my-app.conf")
public class MyProperties {
  Duration reloadPeriod;
}

And I want to use the reloadPeriod in a @Scheduled field like this:

@Service
public class MyService {

   @Scheduled(fixedDelayString = "#{myProperties.reloadPeriod}")
   public void doSomeRecurrentStuff() {
      // some work
   }
}

But this setup will always fail with this error:

Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'myProperties' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?

When I add an "intermediate bean" like this:

@Configuration
public class MyConfigClass {

   @Bean("reloadPeriod")
   Duration reloadPeriod(MyProperties props) {
      return props.getReloadPeriod();
   }
}

then I can reference it without any problems like this: @Scheduled(fixedDelayString = "#{reloadPeriod}")

tldr;

How can I access "like beans" created by @ConstructorBinding via SpEL?

akop
  • 5,981
  • 6
  • 24
  • 51
  • 1
    have you checked [How to reference a bean by type in a SpEL?](https://stackoverflow.com/questions/59771574/how-to-reference-a-bean-by-type-in-a-spel) – Andrey B. Panfilov Jan 15 '23 at 03:01
  • @AndreyB.Panfilov no, I doesn't saw this one. But it is the same question, so mine is duplicated. – akop Jan 16 '23 at 06:43

1 Answers1

1

You can use beanFactory to get the configuration properties bean by its type.

@Scheduled(fixedDelayString = 
            "#{beanFactory.getBean(T(com.package.MyProperties)).reloadPeriod}")
public void doSomeRecurrentStuff() {
    // ...
}

Alternatively, implement SchedulingConfigurer to programmatically set up scheduled tasks.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
    @Autowired
    private MyProperties myProperties;
    
    void doSomeRecurrentStuff() {
        // some work
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addFixedDelayTask(this::doSomeRecurrentStuff, 
              myProperties.getReloadPeriod());
    }
}
Unmitigated
  • 76,500
  • 11
  • 62
  • 80