Search code examples
spring-bootguava

use of @Value Spring annotation during Controller initialization issue


Probably someone else might have asked something similar as well, but I couldn't find an answer that provides a solution that works... I'm in the process of learning spring boot and while I was playing with guava RateLimiter during my experiments I hit the following problem: RateLimiter needs to be created during the Controller initialization, but if I want to load the rate I have to hardcode it, since if I try to load it from props using attributes with @Value Spring annotations it doesn't work. Is there any "trick" around this "limitation"? see code below:

@RestController
public class LoggingController {
    private Logger logger = LoggerFactory.getLogger(LoggingController.class);

    @Value("${count}")
    private Double PERMITS_COUNT;
    @Value("${seconds}")
    private Double PERMITS_PER_SECONDS;
    @Value("${consumed}")
    private int PERMITS_CONSUMED;

//@ Value fails here with NullPointerException
    private RateLimiter rateLimiter = RateLimiter.create(PERMITS_COUNT / PERMITS_PER_SECONDS);
// This works file
private RateLimiter rateLimiter = RateLimiter.create(10d / 60d);

    private AtomicInteger index = new AtomicInteger(0);


    @GetMapping("/logging")
    @ResponseBody
    public String logging (@RequestParam(name="name", required=false, defaultValue="JavaBoss") String name) {

//@Value works fine if used here
        rateLimiter.setRate(PERMITS_COUNT / PERMITS_PER_SECONDS);
        rateLimiter.acquire(PERMITS_CONSUMED);
...

Many thanks in advance...


Solution

  • Use PostConstruct and you should be fine

     @RestController
        public class LoggingController {
            private Logger logger = LoggerFactory.getLogger(LoggingController.class);
        
            @Value("${count}")
            private Double PERMITS_COUNT;
            @Value("${seconds}")
            private Double PERMITS_PER_SECONDS;
            @Value("${consumed}")
            private int PERMITS_CONSUMED;
            
            private RateLimiter rateLimiter;
            
            @PostConstruct 
            private void createRateLimiter() {
             rateLimiter = RateLimiter.create(PERMITS_COUNT / PERMITS_PER_SECONDS);
            }
            
        
            private AtomicInteger index = new AtomicInteger(0);
        
        
            @GetMapping("/logging")
            @ResponseBody
            public String logging (@RequestParam(name="name", required=false, defaultValue="JavaBoss") String name) {
        
        
        ...