SpringBoot cache not working for non parameter methods

Tags: , , ,



I have one spring boot application

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>cachedemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cachedemo</name>
    <description>Demo project for Spring Boot cache</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
            <!-- <version>2.2.6.RELEASE</version> -->
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

CacheDemoAllpication.java

package com.example.cachedemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class CachedemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(CachedemoApplication.class, args);
    }

}

Controller

package com.example.cachedemo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.example.cachedemo.model.Book;
import com.example.cachedemo.service.LibraryService;


@Controller
public class HomeController {

    @Autowired
    private LibraryService service;
    
    
    @RequestMapping("/get")
    public String getBooks(@RequestParam Integer id) {
        
        Book book = service.getBook(id);
        System.out.println(book);
        return book.toString();
    }
}

Service

package com.example.cachedemo.service;

import java.util.HashMap;
import java.util.Map;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import com.example.cachedemo.model.Book;

@Service
public class LibraryService {

//  @Cacheable(value = "bookCache")
    public Book getBook(Integer id) {
        
        System.out.println("*******************************************Method called getBook()************************************");
        
        Map<Integer,Book> bookMap = getBookMap();
        
        return bookMap.get(id);
    }
    
    
    @Cacheable(value = "booksCache", key="#root.methodName")
    private Map<Integer,Book> getBookMap()
    {
        Book b3 = new Book(2,"Peace","Arif");
        Book b2 = new Book(3,"Mumbai City","Shiv Shankar");
        Book b1 = new Book(1,"Test","Sunny");
        
        Map<Integer,Book> bookMap = new HashMap<Integer, Book>();
        bookMap.put(1, b1);
        bookMap.put(2, b2);
        bookMap.put(3, b3);
        
        System.out.println("*******************************************Method called getBookMap()************************************");
        
        return bookMap;
    }

}

In the service class getBookMap() return a Map and I want spring to cache that. For subsequent requests it should return that map from cache. But with current setup It’s not caching anything and getBookMap() method is being executed every time. My first suspect was spring-boot-starter-cache version, but that’s not the case. The behavior is same with latest version as well.

I have tried with/without key=”#root.methodName” but the result is same.

Whereas if I cache method getBook(Integer id) it works just fine which gets me into thinking that no parameter methods are behaving differently.

Answer

  1. @Cacheable won’t work for private methods, make your method public
  2. You can’t call a cacheable method from within the same class. I mean put your Cacheable method into another class and make it public. Call the method from another class. Then it’ll work


Source: stackoverflow