• Documentation
  • Status: Open
  • 2 Major
  • Resolution:
  • Documentation
  • scic
  • Reporter: scic
  • October 24, 2011
  • 0
  • Watchers: 2
  • March 23, 2012

Description

On the page http://www.ehcache.org/documentation/recipes/cachenull the caching of null values is described:

I think there is a problem with the example: The problem is the use of the EhCacheWrapper because after the call to cache.get(id) you don’t know as you get null if the value was null because

  1. we put null in the cache or
  2. the element has not been cached before.

Because get is defined in the Wrapper as: Code:

 public V get(final K key) 
     {
         Element element = getCache().get(key);
         if (element != null) {
             return (V) element.getValue();
         }
         return null;
     }

In either case the element gets fetched from db, but in case 1, since we are caching null values we don’t want to fetch the element anymore as we already marked it as being null.

A possible solution, if you want to use a CacheWrapper is do something like in this (similar as EhCache class handles it):


 	public Value<V> getValueObject(final K key) {
 		Element element = getCache().get(key);
 		return new Value<V>(element);
 	}
 
 package ch.ergon.newom.web.service.cache;
 
 import net.sf.ehcache.Element;
 
 /**
  * Handles null values correctly. Use this object if you want to know if an
  * element was retrieved as null from the cache or the value was returned null
  * because it was not in the cache.
  * 
  * @param <V> encapsulated value
  */
 public class Value<V> {
 	private final V value;
 	private final boolean inCache;
 
 	Value(V element) {
 		if (element == null) {
 			inCache = false;
 		} else {
 			inCache = true;
 		}
 		value = element;
 	}
 	
 	Value(Element element) {
 		if (element == null) {
 			value = null;
 			inCache = false;
 		} else {
 			@SuppressWarnings("unchecked")
 			V val = (V) element.getValue();
 			value = val;
 			inCache = true;
 		}
 	}
 	
 	public V getValue() {
 		return value;
 	}
 
 	public boolean isInCache() {
 		return inCache;
 	}
 	
 	@Override
 	public String toString() {
 		return "[" + value.toString() + ", " + inCache + "]";
 	}
 }

(From http://forums.terracotta.org/forums/posts/list/6096.page)

Comments

Fiona OShea 2011-10-25

Daniel does this forum post answer your question? regards Fiona

From the forums

So this sounds like a discussion of the null object pattern. Specifically, EhCache does support writing nulls for a given key. It’s up to your code implementation to recognize the null and not try and do a “put” on a null value if it previously obtained it from the cache. You can do this by using a wrapper like you’ve done, but a better handler is for the calling method to use the null object pattern, and then not even say call the database or other data store to get the data.

For example in pseudo code: Get object from Cache Object is Null, return new instance of object, call setNull(true) on that Object. Caller gets object, checks “isNull” and if so, returns null. If object is actually null and not a “Null Object instantiation”, query the database, store in the cache.

There’s a number of patterns for this that work remarkably well. The wrapper you listed above only prevents loading into the cache a null value that was previously put in the cache. Additionally, there might be situations where you’d WANT to do this, such as to update the expiration times or other statistics, etc.

Daniel Zeiter 2011-11-09

No this does not answer my question (see the forum post) and there seems to be no more discussion on the topic.

ilevy 2012-03-23

See this forum post for a simple solution:

http://forums.terracotta.org/forums/posts/list/6817.page#34279

The recipe mentioned above is incorrect as mentioned and will be updated.