title: @Cacheable and initialization during startup
body: <p>I would like to initialize all entries in cache during startup of my spring boot application (loading stuff from DB). Ideally, this is done before the application is already ready. So I implemented all loading in <code>@PostConstruct</code>. I remarked, that the cache is not already setup in <code>@PostContruct</code> and I followed some tips to do such initializations in the <code>ApplicationReadyEvent</code>. However, this still does not work as expected:</p>
  
  <p>Even though I already call a <code>@Cacheable</code> Method in <code>ApplicationReadyEvent</code>, the second invocation re-enters the method instead of using the cache.</p>
  
  <p>My Service:</p>
  
  <pre><code>@Service
  public class MyService implements ApplicationListener&lt;ApplicationReadyEvent {
  
    @Cacheable("entry")
    public List&lt;String&gt; getEntry() {
      System.out.println("getEntry called!");
      return Arrays.asList("aaa", "bbb");
    }
  
    @Override
    public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
      System.out.println("*** onApplicationEvent");
      getEntry();
    }
  }
  </code></pre>
  
  <p>My Caffeine CacheManager Config:</p>
  
  <pre><code>@Configuration
  @EnableCaching
  public class CachingConfig {
  
    @Bean
    public CacheManager cacheManager() {
      List&lt;CaffeineCache&gt; caffeineCaches = chacheList(Arrays.asList(
          "entry"
      ));
  
      SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
      simpleCacheManager.setCaches(caffeineCaches);
      System.out.println("*** @Bean CacheManager");
      return simpleCacheManager;
    }
  
    private List&lt;CaffeineCache&gt; chacheList(List&lt;String&gt; cacheNames) {
      return cacheNames.stream().map(s -&gt; new CaffeineCache(s, Caffeine.newBuilder().build()))
          .collect(Collectors.toList());
    }
  
  }
  </code></pre>
  
  <p>A simple REST endpoint using the service:</p>
  
  <pre><code>@RestController
  public class MyController {
  
    @Autowired
    MyService myService;
  
    @GetMapping("/test")
    public void test()
    {
      System.out.println("*** GET /test");
      myService.getEntry();
    }
  }
  </code></pre>
  
  <p>If I start the application and perform two <code>GET /test</code>, I get the following output:</p>
  
  <pre><code>INFO 20120  --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 907 ms
  *** @Bean CacheManager
  INFO 20120  --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
  INFO 20120  --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
  INFO 20120  --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 1.639 seconds (JVM running for 2.473)
  *** onApplicationEvent
  *** getEntry called!
  INFO 20120  --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
  INFO 20120  --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
  INFO 20120  --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 4 ms
  *** GET /test
  *** getEntry called!
  *** GET /test
  </code></pre>
  
  <p>So why does the second invocation of <code>MyService.getEntry</code> (i.e. the first invocation after "Startup") enters the code again?</p>
  
  <p>At the end, I need a solution, which performs the first loading before the application finished to startup - i.e. I will try <code>ContextRefreshedEvent</code> or again <code>@PostConstruct</code> (and <code>@Autowire CacheManager</code> to have it configured before executing <code>@PostConstruct</code>). But the first step would be to get this example here behave as expected. </p>