1

I'm trying to setup a cache using guava, with the following code:

private List<Profile> buildCache() {
        LoadingCache cache = CacheBuilder.newBuilder()
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .maximumSize(40)
                .build(
                        new CacheLoader<Profile, List<Profile>>() {
                            @Override
                            public List<Profile> load(Profile profile) throws Exception {
                                Profile profile1 = new Profile();
                                Profile.setEmployed(true);
                                return profileDAO.getAllProfiles(Profile1, null);
                            }
                        }
                );
        return (List<Profile>) cache;
    }


public List<Profile> getAllProfiles(Profile profile, Integer size) throws Exception {
        return profileDAO.getAllProfiles(profile, size);
    }

The idea here is that this will create a cache using get all profile. The method for that uses a new profile object to set a boolean on whether that employee is employed or not. The size variable means that the method will return however many indicated. When null, it defaults to top 10.

I have two issues: 1. This is the first time I have ever used a cache, so I really do not know if I am doing this correctly. 2. I cannot find anything in the documentation on how to implement this within my app. How am I supposed to call this? I tried modifying the getAllProfiles method to return it:

public List<Profile> getAllProfiles(Profile profile, Integer size) throws Exception {
        return buildCache();
    }

But that simply returns an exception that I cannot cast the cache into a java list:

Exception occurred: java.lang.ClassCastException: com.google.common.cache.LocalCache$LocalLoadingCache cannot be cast to java.util.List

If its any help, my app is also using spring, so I've also been doing research into that. Is there any difference between springframework.cache.guava and google.common.cache, or is it just Spring's inbuilt guava cache?

SVill
  • 331
  • 5
  • 22
  • 55
  • does your `Profile` overrides hashCode/equals? – Eugene May 16 '18 at 13:42
  • In the core object? Yes. – SVill May 16 '18 at 13:44
  • I don't understand how this is suppose to work to begin with, you want to cache some profiles (`List`) from some *other* profile? May be you wan to cache active profiles only? – Eugene May 16 '18 at 13:47
  • That's exactly what I'm trying to do (caching the top 10 active profiles). But, like I said, I'm really not sure how to implement this correctly. – SVill May 16 '18 at 13:50
  • think about it this way - suppose you want to query some users based on firstname, so your cache is `String, User`, `load` method is called when that `String` is *not* in the cache and later cached; on a second call your load will not be called. So basically you just do `cache.get(String firstName)` - the rest will be done by the cache – Eugene May 16 '18 at 13:51
  • this is still a bit un-clear, you want to cache first 10 active users (but your cache has 40 entries); than your DAO method makes little sense too - it should be something like `profileDAO.getTop10ActiveProfiles` or `profileDAO.getAllProfiles(boolean active)` and then do a `subList` from that to get the first 10. In this case your cache would be something like `Boolean, List` and they will be valid for the ammount that you set via `expireAfterWrite` – Eugene May 16 '18 at 14:01

1 Answers1

1

Ok, I think I managed to figure it out:

private LoadingCache<Integer, List<Profile>> loadingCache = CacheBuilder.newBuilder()
            .refreshAfterWrite(10,TimeUnit.MINUTES)
            .maximumSize(100).build(
            new CacheLoader<Integer, List<Profile>>() {
                @Override
                public List<Profile> load(Integer integer) throws Exception {
                    Profile profile= new Profile();
                    if (integer == null) {
                        integer = 10;
                    }
                    return profileDAO.getAllProfiles(profile, integer);
                }
            }
    );

First, I should have specified the key and value being passed into LoadingCache, in this case, an Integer and a List of Profile. Also, when I declared the new CacheLoader in the build function, I should have kept that layout of key and value. Finlly, when calling the getAll method, I should have loaded using the key Integer, not a profile object.

As for calling the function:

public List<Profile> getAllProfiles(Profile profile, Integer size) throws Exception {
        return loadingCache.get(size);
    }

This serves to get lists of certain legnths that are stored in the cache. If the list of that length is not in the cache, the getAll method will run, using the size varaible you pass to it.

@Eugene, Thank you for your help. Your explanation on the load method really helped put the cache into perspective for me.

SVill
  • 331
  • 5
  • 22
  • 55