How to load @Cache on startup in spring?

spring cache list of objects
spring-boot-starter-cache example
spring boot cache example mkyong
spring boot cache auto refresh
spring cache get all keys
spring cacheable key
spring boot distributed cache
spring boot cache not working

I'm using spring-cache to improve database queries, which works fine as follows:

@Bean
public CacheManager cacheManager() {
    return new ConcurrentMapCacheManager("books");
}

@Cacheable("books")
public Book getByIsbn(String isbn) {
    return dao.findByIsbn(isbn);
}

But now I want to prepopulate the full book-cache on startup. Which means I want to call dao.findAll() and put all values into the cache. This routine shall than only be scheduled periodically.

But how can I explicit populate a cache when using @Cacheable?

Just use the cache as before, add a scheduler to update cache, code snippet is below.

@Service
public class CacheScheduler {
    @Autowired
    BookDao bookDao;
    @Autowired
    CacheManager cacheManager;

    @PostConstruct
    public void init() {
        update();
        scheduleUpdateAsync();
    }

    public void update() {
        for (Book book : bookDao.findAll()) {
            cacheManager.getCache("books").put(book.getIsbn(), book);
        }
    }
}

Make sure your KeyGenerator will return the object for one parameter (as default). Or else, expose the putToCache method in BookService to avoid using cacheManager directly.

@CachePut(value = "books", key = "#book.isbn")
public Book putToCache(Book book) {
    return book;
}

Getting Started, For all Spring applications, you should start with the Spring Initializr. This example needs only the Spring cache abstraction dependency. Just add the spring-boot-starter-cache and caching implementation JAR file to the pom.xml file. Annotate with @EnableCaching in the @Configuration file. It is not required to add the caching manager beans in the @Configuration file.

I have encountered the following problem when using @PostConstruct: - even though the method I wanted to be cached was called, after calling it from swagger, it still didn't use the cached value. Only after called it once more.

That was because @PostConstruct is too early for caching something. (At least I think that was the issue)

Now I'm using it more late in the startup process and it works without problems:

@Component
public class CacheInit implements ApplicationListener<ApplicationReadyEvent> {

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
       //call service method
    }

}

Spring boot caching tutorial with example, Learn to easily manage application cache from Spring boot caching support. we need to manipulate the cacheing manually to put (update) cache before method call. To do this we need to go to https://start.spring.io/ and give the maven  For Spring users, here is a list of tips to keep in mind when implementing caching annotations. Beware of the Default Cache Keys. Caching a method outcome is really easy to do.

If having all instances of Book in memory at startup is your requirement than you should store them in some buffer yourself. Putting them in the cache with the findAll() method means that you must annotate findAll() with @Cacheable. Then you would have to call findAll() at startup. But that does not mean that calling getByIsbn(String isbn) will access the cache even if the corresponding instance has been put in the cache when calling findAll(). Actually it won't because ehcache will cache method return value as a key/value pair where key is computed when method is called. Therefore I don't see how you could match the return value of findAll() and return value of getByIsbn(String) because returned types are not the same and moreover key won't never match for all your instances.

Getting Started with Caching in Spring Boot Applications, Getting Started with Caching in Spring Boot Applications. One of the features of the Spring Framework is a cache you can transparently add to your code. All you need to do is set an annotation on a method you want to cache and configure the caching mechanism itself. I am developing a java web application in which I want to cache all the data present in a table during server start up. Also if there are any changes in DB values, I wish to refresh the cache (without restarting the server). I am looking for some material in spring which may help me in achieving that. But I am not able to figure it out.

An option would be to use the CommandLineRunner for populating the cache on startup.

From official CommandLineRunner documentation, it is an:

Interface used to indicate that a bean should run when it is contained within a SpringApplication.

Hence, we just need to retrieve the list of all available books and then, using CacheManager, we populate the book cache.

@Component
public class ApplicationRunner implements CommandLineRunner {
    @Autowired
    private BookDao dao;

    @Autowired
    private CacheManager cacheManager;

    @Bean
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager("books");
    }

    @Override
    public void run(String... args) throws Exception {

        List<Book> results = dao.findAll();

        results.forEach(book -> 
            cacheManager.getCache("books").put(book.getId(), book));
    }
}

How to load data to Ehcache when the application starts, You can write a startup-class(servlet or something like that-load first) to load the entire cache with the data you require at the startup via spring and its init method(to get the data from database) is called after the load method  For all Spring applications, you should start with the Spring Initializr. The Initializr offers a fast way to pull in all the dependencies you need for an application and does a lot of the set up for you. This example needs only the Spring cache abstraction dependency. The following image shows the Initializr set up for this sample project:

As Olivier has specified, since spring caches output of function as a single object, using @cacheable notation with findAll will not allow you to load all objects in cache such that they can later be accessed individually.

One possible way you can load all objects in cache is if caching solution being used provides you a way to load all objects at startup. E.g solutions like NCache / TayzGrid provides Cache startup loader feature, that allows you to load cache at startup with objects using a configurable cache startup loader.

A Guide To Caching in Spring, How to enable, configure and make good use of the Caching Abstraction in Spring. Spring cache is not working when calling cached method from another method of the same bean. Here is an example to explain my problem in clear way. Configuration: <;cache:annotation-driven cache-

Spring Cache Tutorial, Spring Framework provides support for caching means we can cache the frequently used data in the application at startup time. For example, you can put multiple @CacheEvict or @CachePut annotation inside @Caching  Hi I am using EhCache for our project, i used spring based annotation to create cache and mapped the cache in ehcache.xml. can you please suggest me how to load data to cache during application start Please reply as soon as possible

Spring Boot + Caching - Ihor Kosandiak, High load — when your service faces big pressure from users;; Complicated Business Logic — when there are lots of stuff that needs to be  For caching we need spring-boot-starter-cache and cache-api dependency as well as the dependency ehcache as a cache provider. 5.2 Enable Caching To enable caching support in Spring Boot, we need a simple configuration class that must be annotated with @EnableCaching .

Spring Cache Annotation Tips and Tricks, This list of Spring cache annotation tips and tricks will help clarify what Be aware that only the first would be an actual cache put (inserting a 

Comments
  • stackoverflow.com/questions/53030289/…
  • What is BookService, I don't see any mention of that in OP's question. Who calls putToCache?
  • Used similar approach. @EventListener with ContextRefreshedEvent did the trick for us.
  • Yes that would be an option, BUT very bad for performance as I'm hitting the DB n-times during startup for every entry. And moreover, it is somehow redundant as I already have all my books by findAll(). So I'm looking for a way to get these books into the cache without another roundtrip to db.
  • Then can do something like
  • Edited the soln accordingly.