title: Pre-load values for a Guava Cache
body: <p>I have a requirement where we are loading static data from a database for use in a Java application. Any caching mechanism should have the following functionality:</p>
  
  <ul>
  <li>Load all static data from the database (once loaded, this data will not change)</li>
  <li>Load new data from the database (data present in the database at start-up will not change but it is possible to add new data)</li>
  </ul>
  
  <p>Lazy loading of all the data isn't an option as the application will be deployed to multiple geographical locations and will have to communicate with a single database. Lazy loading the data will make the first request for a specific element too slow where the application is in a different region to the database.</p>
  
  <p>I have been using the MapMaker API in Guava with success but we are now upgrading to the latest release and I can't seem to find the same functionality in the CacheBuilder API; I can't seem to find a clean way of loading all data at start-up.</p>
  
  <p>One way would be to load all keys from the database and load those through the Cache individually. This would work but would result in N+1 calls to the database, which isn't quite the efficient solution I'm looking for.</p>
  
  <pre><code>public void loadData(){
      List&lt;String&gt; keys = getAllKeys();
      for(String s : keys)
          cache.get(s);
  }
  </code></pre>
  
  <p>Or the other solution is to use a ConcurrentHashMap implementation and handle all of the threads and missing entries myself? I'm not keen on doing this as the MapMaker and CacheBuilder APIs provide the key-based thread locking for free without having to provide extra testing. I'm also pretty sure the MapMaker/CacheBuilder implementations will have some efficiencies that I don't know about/haven't got time to investigate.</p>
  
  <pre><code>public Element get(String key){
      Lock lock = getObjectLock(key);
      lock.lock();
      try{
          Element ret = map.get(key)
          if(ret == null){
              ret = getElement(key); // database call
              map.put(key, e);
          }
          return ret;
      }finally {
          lock.unlock();
      } 
  }
  </code></pre>
  
  <p>Can anyone think of a better solution to my two requirements?</p>
  
  <hr>
  
  <p><em><strong>Feature Request</em></strong></p>
  
  <p>I don't think pre-loading a cache is an uncommon requirement, so it would be nice if the CacheBuilder provided a configuration option to pre-load the cache. I think providing an Interface (much like CacheLoader) which will populate the cache at start-up would be an ideal solution, such as:</p>
  
  <pre><code>CacheBuilder.newBuilder().populate(new CachePopulator&lt;String, Element&gt;(){
  
      @Override
      public Map&lt;String, Element&gt; populate() throws Exception {
          return getAllElements();
      }
  
  }).build(new CacheLoader&lt;String, Element&gt;(){
  
      @Override
      public Element load(String key) throws Exception {       
          return getElement(key);
      }
  
  });
  </code></pre>
  
  <p>This implementation would allow the Cache to be pre-populated with all relevant Element objects, whilst keeping the underlying CustomConcurrentHashMap non-visible to the outside world. </p>