Search code examples
javaspringspring-bootspring-cache

Spring Cache not working as a compute property


I want to use a mechanism for create a one time compute function. I try to use Spring Caching. But it does not working. Please help me to solve this problem. My code like as below,

Gradle Dependency

compile 'org.springframework.boot:spring-boot-starter-cache'

Main Class of Spring Boot Application

@SpringBootApplication
@EnableCaching
public class Application {

    public static ApplicationContext applicationContext;

    public static void main(String[] args) {
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
        // todo: Try to save response text and request body
        applicationContext = SpringApplication.run(Application.class, args);
    }

    @Bean
    WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
            @Override
            public void addResourceHandlers(ResourceHandlerRegistry registry) {
                registry
                        .addResourceHandler("/**")
                        .addResourceLocations("classpath:/")
                        .setCacheControl(CacheControl.maxAge(3600, TimeUnit.SECONDS).noTransform().mustRevalidate());
            }
        };
    }
}

My Coputational property and Test method

public String test(){
        return hello();
    }


    @Cacheable("hello")
    public String hello(){
        System.out.println("hello");
        return "Hello";
    }

Solution

  • The @Cacheable annotation caches the values when it is called from outside your @Bean so calling it from another method inside your bean will not work.

    try something like

    @Bean 
    public class CachingBean {
        @Cacheable("hello")
        public String hello(){
            System.out.println("hello");
            return "Hello";
        }
    }
    
    @Service
    public class CallerService {
    
      @Autowired
      private CachingBean cachingBean;
    
      // Setters, constructors...
    
      public String test(){
            return cachingBean.hello();
      }
    }
    

    And then it should work. That's because the @Cacheable annotation creates a proxy around the method call when it is injected as a Bean, so a direct call (to an instance created directly) or an internal call are not intercepted and the caching mechanism does not even see those calls.

    I still sometimes forget about it and get biten by it at the beginning :). Cheers!