Search code examples
javaguava

Howto load guava with entries


I need a cache of failed entries, which I am trying to build using the following statements:

    failedJobCache =
            CacheBuilder.newBuilder()
                    .maximumSize(100) // maximum 100 records can be cached
                    .expireAfterAccess(30, TimeUnit.MINUTES) // cache will expire after 30 minutes of access
                    .build(new CacheLoader<String, JobDto>() {
                        @Override
                        public JobDto load(String s) throws Exception {
                            JobDto found = failedJobCache.get(s);
                            if (found != null)
                                return found;
                            else
                                return null;
                        }
                    });

And:

// add failed entries
failedJobCache.put(jobDto.getUniqueId(), jobDto);

// respective check before running the job if its
// already in the cache and should be skipped:
JobDto existing = failedJobCache.get(jobDto.getUniqueId());
if (existing != null) {
    logger.debug("Nothing to do, job already processed!" + jobDto.getUniqueId());
    return;
}

Unfortunately I encounter:

Exception in thread "main" com.google.common.util.concurrent.UncheckedExecutionException: java.lang.IllegalStateException: Recursive load of: ...

Question How do I add only failed entries to the cache?


Solution

  • CacheLoader.load(K) is only called if there isn't "an already-loaded value for a given key" (CacheBuilder.build(LoadingCache)).

    As such, calling LoadingCache.get(K) from CacheLoader.load(K) creates a recursive load that, if allowed to execute, would recurse too deeply causing a StackOverflowError to be thrown.

    From the information provided in your example it does not appear you need a LoadingCache<K, V> but just a Cache<K, V>. Call CacheBuilder.build() without a CacheLoader<K, V>.

    See CachesExplained · google/guava Wiki for more details.