2
votes

I'm trying to use google guava cache on a program but am not quite getting how it works.

I'm loading up the cache and then at a later stage i'm trying to check if an item exists in the cache, my code below doesnt quite work

The getIfPresent returns null if it doesnt exist but the load which calls it bombs out after with the error

Exception in thread "main" com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key

 private static LoadingCache<String, Image> imageCache
          = CacheBuilder.newBuilder()
                .build(new CacheLoader<String, Image>() {

            @Override
            public Image load(String key) throws Exception {                    
                if (getImage(key) != null) {                    
                    return getImage(key);                       
                }               
                return null;
            }                 
          });           

public static Image getImage(String key) throws ExecutionException {

    return imageCache.getIfPresent(key);

}

this means i cant check for the presense of the item in the cache like so

    try {
        readImage = imageCache.get(fileName);
    } catch (ExecutionException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

    if (readImage != null) {


    }

can someone explain to me what i'm doing wrong here?

3
Your cache loader is calling a method which calls the cache which calls the cache loader... Your load method should actually do the loading of the image. - Andy Turner

3 Answers

4
votes

If you need manage null values in your Loader, use Guava Optional

@Override
public Optional<Image> load(String key) throws Exception {
    return Optional.fromNullable(getImage(key));
}

Image getImage(String key) throws ExecutionException {
    //your code to get image from database, or other source
    return yourCodeToGetImageFromTheSource(key);
}

Your client code, can be:

try {
    Optional<Image> imageCached = imageCache.get(fileName);
} catch (ExecutionException e1) {
    // TODO error handling
}

if (imageCached.isPresent()) {
    Image img = imageCached.get();
} else {
    //your code when img is null
}
3
votes

First Of All you cannot return null from your load method. If you want check whether a certain key exists in your cache you can simply get the ConcurrentMap used within the LoadingCache through

Map<K,V> imageMap = imageCache.asMap()

And simply use that map as any other map i.e. use the containsKey method on the Map to check whether a key is present and so on

1
votes

The javadoc of CacheLoader#load(String) states

Parameters:

  • key the non-null key whose value should be loaded

Returns:

  • the value associated with key; must not be null

Throws:

  • Exception - if unable to load the result

You've implemented it as returning null, that breaks the CacheLoader contract.