Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use cache on controller/service in spring boot?

I'm trying to add caching on my spring-boot app by following instruction on https://www.java4s.com/spring-boot-tutorials/how-to-configure-cache-in-spring-boot-applications/, but it doesn't work. I'm not entirely sure how to test it. I have a system.out.print under controller like in this article. If cache works then it will print "test" only once but return the same result from the request with same input. I have my code as below:

CurrencyController.java

    @RequestMapping(method = RequestMethod.POST)
    @Cacheable(value="currency")
    public ResponseEntity getExchangedCurrency(final @RequestBody CurrencyExchange currencyExchange) {
        System.out.println("Test");
        return ResponseEntity.ok()
              .headers(responseHeaders)
              .body(currencyService.calculate(currencyExchange));
    }

App.java

@SpringBootApplication
@EnableCaching
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);



    }
}

like image 226
Chandara Chea Avatar asked Mar 04 '23 03:03

Chandara Chea


1 Answers

The way @Cacheable annotation works is utilizing method parameter as key by default for the caching map. In this case currencyExchange object. Since it's object on each request spring request dispatcher creates new object and cache manager keeps as separate key.

Req1 -> object1 -> map.put(object1, response)

Req2 -> object2 -> map.contains(object2) -> false -> map.put(object2, response)

If you think for all the post request send the same response from cache which doesn't the case always, you can change the key like this.

@RequestMapping(method = RequestMethod.POST)
@Cacheable(value="currency", key="#root.method")
public ResponseEntity getExchangedCurrency(final @RequestBody CurrencyExchange currencyExchange) {
    System.out.println("Test");
    return ResponseEntity.ok()
          .headers(responseHeaders)
          .body(currencyService.calculate(currencyExchange));
}

You can also use Spring Expression Language (SpEL) expression for defining key, if your currencyExchange has method getId() which can be used as potential cache key you can do like this

@Cacheable(value="currency", key="#root.args[0].getId()")

To clear cache Add @EnableCaching on spring boot main class, fixedDelay in milliseconds

@CacheEvict(allEntries = true, value = {"currency"})
@Scheduled(fixedDelay = 5000 ,  initialDelay = 5000)
public void clearCache() {
    System.out.println("Cache cleared");
}
like image 179
Pasupathi Rajamanickam Avatar answered Mar 06 '23 12:03

Pasupathi Rajamanickam