• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Jeanne Boyarsky
  • Ron McLeod
  • Tim Cooke
Sheriffs:
  • Devaka Cooray
  • paul wheaton
  • Mark Herschberg
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Stephan van Hulst
  • Frits Walraven
  • Jj Roberts
Bartenders:
  • Carey Brown
  • salvin francis
  • Piet Souris

use of @Value Spring annotation during Controller initialization issue

 
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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);
...
 
Sheriff
Posts: 22080
113
Eclipse IDE Spring VI Editor Chrome Java Ubuntu Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Your ordering is incorrect. The injection of these values occurs after the object has been created, but the failing uses of them occurs during object initialization.

An overview of what's happening:
  • Spring Boot creates an instance.
  • Fields with explicitly initialization values are assigned. This is where you get the exception.
  • The constructor is called. You don't have an explicit one, so the implicit default constructor is called.
  • After the constructor ends, Spring Boot auto-wires values and dependencies.


  • Since Spring Boot supports injecting values and dependencies in constructors, this is actually easy to fix:

    You can even omit the double and int fields if you don't need them but only the rate limiter.
     
    So you made a portal in time and started grabbing people. This tiny ad thinks that's rude:
    the value of filler advertising in 2021
    https://coderanch.com/t/730886/filler-advertising
    reply
      Bookmark Topic Watch Topic
    • New Topic