2

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?

blu10
  • 534
  • 2
  • 6
  • 28
  • 2
    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 Jun 01 '15 at 21:19

3 Answers3

4

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
}
Omar Hrynkiewicz
  • 502
  • 1
  • 8
  • 21
3

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

Nahush Farkande
  • 5,290
  • 3
  • 25
  • 35
1

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.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • thanks, so is there no way to achieve what im trying to do here with google guava?... im new to it and couldnt find that many examples – blu10 Jun 01 '15 at 16:39
  • @blu10 I don't really understand what you are trying to do. Your cache loader is trying to use the cache to load something. The cache loader should provide the cache value for the key. You seem to be doing things backwards. – Sotirios Delimanolis Jun 01 '15 at 16:43
  • i guess im not understanding how it works completely.... i was looking for a quick mechanism to cache objects and also be able to check it they were present in the cache... Checking that they are present is the part that im not getting.... – blu10 Jun 01 '15 at 16:59
  • 2
    @blu10 Don't register a `CacheLoader`. Just use `getIfPresent`. It will return the value _if it is present_ or `null` if it's not. – Sotirios Delimanolis Jun 01 '15 at 17:01