Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java object references with cache layer

We've created a caching layer to our J2EE-application. In this instance we use Ehcache. This has created a few challenges.

Let's take this example.

OrderItem orderitem = cache.getOrderItemByID("id");
OrderItem old_orderitem = cache.getOrderItemID("id");

orderitem.setStatus(1);
old_orderitem.setStatus(2);

If we're not carefull, any changes made to either of those objects will affect the other (they reference the same object). Saving orderitem back to the dabase would make it have status=2

How would we solve this the best way?

We've tried making a .copyObject() method to each object. Which just creates a new object and sets all the values. But this doesn't seem like a good solution.

The example was just to illustrate. The code is far more complex than that, but the result is the same.

**********************Update 15.07.2010 **************************************************

In EHCache 2 there are some options to to turn on copyRead() and copyWrite(). And this solves all my problems :)

like image 507
Tommy Avatar asked Jan 07 '10 17:01

Tommy


2 Answers

This is a problem with mutable state. It isn't only caching, it's any time you could have multiple references to the same object and that object is mutable. For example:

HashMap map = new HashMap();
map.put("one", new OrderItem());
OrderItem one = map.get("one");
OrderItem two = map.get("one");
one.setStatus(1);
two.setStatus(2);

Will have exactly the same problem. This becomes even more complicated when you have a concurrent environment. One way to solve this is to only have immutable objects. That way, if you want an object with different state, you're going to have to make a new one. It also makes concurrent programming easier.

You're right to consider copying the object. Your options are:

  • Cloning
  • Deep copying via serialization
  • Deep copying via copy constructors

Each has their strengths and weaknesses and which one works best will depend on your environment.

like image 74
Jamie McCrindle Avatar answered Oct 04 '22 20:10

Jamie McCrindle


It sounds like you want to cache the data representing an object (for example, the results of a database query) rather than an object itself (for example, session data for a user that you may want to retrieve elsewhere).

If this is the case, your custom cacheing layer (around ehcache) needs to create an object from the cache data when a user makes a request - this will give you a unique object every time and you won't get object interference.

like image 22
Robert Christie Avatar answered Oct 04 '22 20:10

Robert Christie