Skylar Sutton Skylar Sutton - 8 months ago 34
Java Question

Guava CacheLoader Misses

I'm at a loss here.

I've had really good luck manually loading/inserting into a Guava cache, but I decided it should be more "thread safe" (via the CacheLoader).

When I refactored to use the CacheLoader.load style syntax my cache stopped working. Every get() is a cache miss now, and kicks off a call to load().

Am I missing something really simple?


public class DatabasePropertyCache implements RemovalListener<DatabasePropertyCache.Key, Optional<Object>> {

//InitializeOnDemand style singleton
private static class Singleton {
static DatabasePropertyCache INSTANCE = new DatabasePropertyCache();
public static DatabasePropertyCache getInstance() {
return Singleton.INSTANCE;
private DatabasePropertyCache() {
logger = Logger.getLogger(DatabasePropertyCache.class);
cache = CacheBuilder
.expireAfterWrite(24, TimeUnit.HOURS)
new CacheLoader<Key, Optional<Object>>() {

public Optional<Object> load(Key key) throws Exception {
Object propertyValue = [performs a query]
return Optional.fromNullable(propertyValue);

private final LoadingCache<Key, Optional<Object>> cache;
private final Logger logger;

public void onRemoval(RemovalNotification<Key, Optional<Object>> arg0) {
if(logger.isDebugEnabled()) {
logger.debug(String.format("Cached database property expiring %s", arg0.getKey().toString()));

* Returns a cached value. If it has never been cache before, it will be fetched from the database.
* @param value
* @param locale
* @param dataset
* @return
public Object getObject(String id, DatabasePropertiesEnum property, Locale locale) {
Key key = new Key(id, property, locale);

try {
return cache.get(key).orNull();
catch (ExecutionException eex) {
logger.warn(String.format("Error fetching database property %s", key.toString()), eex);
return null;

protected class Key {

private static final String TOSTRING_TEMPLATE = "DatabasePropertyCache.Key[dataset=%s, locale=%s, property=%s]";

private String id;
private DatabasePropertiesEnum property;
private Locale locale;

public Key(String id, DatabasePropertiesEnum property, Locale locale) { id; = property;
this.locale = locale;

public int hashCode() {
return new HashCodeBuilder()

public String getId() {
return id;

public DatabasePropertiesEnum getProperty() {
return property;

public Locale getLocale() {
return locale;

public String toString() {
return String.format(TOSTRING_TEMPLATE, id, locale.toString(),;


Object cacheHit = DatabasePropertyCache.getInstance().getObject("some_id", DatabasePropertiesEnum.SOME_KEY, [users current locale]);

Answer Source

Key class must correctly implement equals() and hashcode().

You could use the Guava EqualsTester to test your equals and hashCode:

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download