Search code examples
javaguavagoogle-guava-cache

Using Google Guava to get List


I am new to Guava and I want to return comma separated list of users essentially a String. I am using one third party API to fetch the list. I want to cache that list and return that entire list if user queries.

I looked at few examples online and they use LoadingCache<k, v> and CacheLoader<k,v>. I do not have any second argument and usernames are unique. Our application is not going to support individual querying on the user

Is there any flavor of / I can twik LoadingCache which will allow me to do that? Something like

LoadingCache<String> 
.. some code .. 
CacheLoader<String> { 
/*populate comma separated list_of_users if not in cache*/ 
return list_of_users
}

Solution

  • As you've no doubt seen, the pattern for a LoadingCache is:

     LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
       .maximumSize(1000)
       .expireAfterWrite(10, TimeUnit.MINUTES)
       // ... other configuration builder methods ...
       .build(
           new CacheLoader<Key, Graph>() {
             public Graph load(Key key) throws AnyException {
               return createExpensiveGraph(key);
             }
           });
    

    If your service doesn't take a key, then you could just ignore it, or use a constant.

     LoadingCache<String, String> userListSource = CacheBuilder.newBuilder()
       .maximumSize(1)
       .expireAfterWrite(10, TimeUnit.MINUTES)
       // ... other configuration builder methods ...
       .build(
           new CacheLoader<String, String>() {
             public Graph load(Key key) {
               return callToYourThirdPartyLibrary();
             }
           });
    

    You can hide the fact that the ignored key exists at all, by wrapping it in another method:

      public String userList() {
            return userListSource.get("key is irrelevant");
      }
    

    It doesn't feel as if you need all the power of a Guava cache in your use case. It expires the cache after a time period, and supports removal listeners. Do you really need this? You could write something very simple instead like:

     public class UserListSource {
         private String userList = null;
         private long lastFetched;
         private static long MAX_AGE = 1000 * 60 * 5; // 5 mins
    
         public String get() {
            if(userList == null || currentTimeMillis() > lastFetched + MAX_AGE) {
                 userList = fetchUserListUsingThirdPartyApi();
                 fetched = currentTimeMillis();
            }
            return userList;
         }
     }