irfanhasan
irfanhasan

Reputation: 51

Spring Boot - cache not working, how to set cache up correctly?

My application is on Spring boot 1.5.1

I have looked up all common problems related to caching not working in spring boot (calling a cacheable method from the same class, etc) and I still can't seem to pinpoint why my method is not cacheing. I am just trying to use the simple cache built into Spring (ie the concurrent hashmap).

Setup: in pom.xml I added this

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

My configuration class is the following:

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

}

I have a controller class that has the following method to get a list of versions.

 @RequestMapping(value = "/getVersionList", method = RequestMethod.GET)
 public JSONObject getVersionList() {
    JSONObject retJSON = new JSONObject();
    List<String> versions = fetchVersionService.getVersionList();
    retJSON.put("versions", versions);
    return retJSON;
}

And the FetchVersionService class where I have the cacheable method to cache this versions list

@Cacheable("versions")
public List<String> getVersionList() {
    System.out.println("If there is something in the cache, it should not hit here.");
    return randomService.getVersions(); //another service class that gets versions from a remote location, which takes a long time
}

Whenever I make multiple GET calls to this function, it always goes inside the function even though I only expect to it execute the function once. For some reason it isn't cacheing the results. Any ideas where I went wrong with my setup? Thanks a lot.

Upvotes: 5

Views: 15752

Answers (3)

Sanjay Bharwani
Sanjay Bharwani

Reputation: 4829

Below is an End to end working code to show case Caching implementation using SpringBoot.

@Cacheable("movies")
  public List<String> getMoviesList() {
   //logic to fetch movies using API call over webClient
  return moviesList;
}

Now this code makes the response of getMoviesList cacheable due to annotation @Cacheable("movies") However this is not enough, as it needs bean of CacheManager as well. In SpringBoot this is simplified, so all you need is @EnableCaching This annotation can go in your main class with @SpringBootApplication as shown below

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

Now depending on your business workflow, you can decide the cache eviction policy.

@CacheEvict(value = "movies", allEntries = true)
  @Scheduled(fixedDelay = 12, timeUnit = TimeUnit.HOURS)
  public void evictMoviesFromCache() {
    // Nothing to do. Annotations cover functionality
    log.info("Evicting Movies from cache.");
  }

Above code evicts the code at scheduled interval of 12 hrs.

Alternatively, you could evict it manually, as shown below.

@Component
public class CacheManagerService {
  @CacheEvict("movies")
  public void evictMoviesFromCache(final String networkRef) {
    // nothing to add as this method is to evict the cache
  }
}

And Autowire CacheManagerService in your code and invoke the method explicitly. for e.g.

@Service
@RequiredArgsConstructor
@Slf4j
public class MoviesCacheManager {
  private final CacheManagerService cacheManagerService;
  private final MoviesClient moviesClient;

public List<Location> refreshMovies() {
    cacheManagerService.evictMoviesFromCache();
    var movies = moviesClient.getMovies().collectList().block();
    return Optional.ofNullable(movies).orElse(emptyList());
  }
}

Reference: https://www.baeldung.com/spring-cache-tutorial

Upvotes: 2

NoisyFlasher
NoisyFlasher

Reputation: 188

In the comments under this question @irfanhasan mentions that they had imported the wrong package but there was no certain response. I faced the same problem. I tried to use @Cachable annotation but it wasn't work. I found that it was imported as:

import springfox.documentation.annotations.Cacheable

Instead of:

import org.springframework.cache.annotation.Cacheable;

Look carefully for your IDE imports.

Upvotes: 13

artin2
artin2

Reputation: 146

In the comments under this question, @irfanhasan mentions that they had imported the wrong package and @xetra11 replied asking which package was wrong which there was no reply to. I am not @irfanhasan but it might have been the following mixup: "You can also use the standard JSR-107 (JCache) annotations (such as @CacheResult) transparently. However, we strongly advise you to not mix and match the Spring Cache and JCache annotations."

Upvotes: 1

Related Questions