Declarative Caching of Java Object Properties

Introduction

Caching is a power mechanism for data access optimization, used for solving various problems:

  • in the CPU, to increase RAM data access speed
  • in the OS, to increase HDD data access speed
  • in proxy-servers, to increase Internet document access speed
  • and in many other cases

Caching is also very useful for developing program systems;it saves calculation resources when a cached object property is accessed repeatedly. Unfortunately, object property caching for complex systems is not as simple as it is desirable. The main complexities are not in caching itself, but in implementing timely cache actualization. In fact, if a property is calculated in a complex way, changing any properties of how this one is calculated should result in actualization of the calculated property cache. If it is not done, users of the object will see no change of its state because they will address an irrelevant cache state.

Example of Object Property Caching

Here a simple example where caching is relevant:

public class CachePattern {
   private Integer area=null;

   public int getWidth(){
      ...
   }

   public int getHeight(){
      ...
   }

   public int getArea(){
      if (area == null)
         area = new Integer(getAreaCalculated());
      return area;
   }

   private int getAreaCalculated(){
      return getWidth()*getHeight();
   }

   public void clearArea (){
      area = null;
   }
...

If you assume that the methods getWidth and getHeight may require significant calculation resources—for instance, they address to some external data storage—it is quite reasonable to implement caching in the getArea method above. At the same time, you should provide for the cache clearance method clearArea to be called each time the width or height are changed, as follows:

public void setWidth(int width){
   ...
      clearArea();
}

public void setHeight(int height){
   ...
      clearArea();
}

Cache clearance programming can be a very complex task that limits the applicability of the caching approach in present program architectures. The task becomes more complicated if a property is calculated from other calculated properties and so forth. In fact, if a calculation rule for a property has changed, the program code, serving for caching, should be adapted accordingly. This can result in hard-to-reveal mistakes and requires additional programmers’ efforts.

Object Property Caching with Refreshable Object Library

Programmer working efficiency in the part of caching implementation could be increased if all tasks of tracking dependencies among calculated properties were solved by a service code, and the programmer defined getters to be cached or not in a declarative manner. It would avoid mistakes in caching in principle because changes in object property calculation rules would not require a programmer’s ivolvement to support caching procedures in a relevant state. To solve the task, the refreshable object library for Java was elaborated.

To deliver a programmer from the necessity of tracking changes of source properties in the example above, it is sufficient to add the @Refreshable annotation for the class CachePattern:

@Refreshable
public class CachePattern {

and to create objects of the class with the help of WrapManager.newInstance of this library:

public static CachePattern newCachePattern (){
   return WrapManager.newInstance(CachePattern.class);
}

Objects created in this way are under the control of the refreshable object library that takes caching management functions on itself. The level of caching control can be different. In the simplest case, the library can provide execution of appropriate clear methods. For instance, in the above example the clearArea method will be called automatically right after any of the setWidth or setHeight methods have finished.

Why? How does the refreshable object library determines that the clearArea method should be called right after the setWidth and setHeight methods have completed? The answer is as follows. First of all, setWidth and setHeight are setters for those properties, the getters of which are getWidth and getHeight accordingly. Second, the body of the getArea getter, which calculates your result property, contains executions for both the getWidth and getHeight getters, so the result property depends on these two properties. When any of the properties is changed, the cache for the area property should be cleared. At the end, the refreshable object mechanism looks for the method named clear<property name>, clearArea in your case, and executes it right after any of the setWidth or setHeight setters has finished.

So, you lightened a programmer’s life in the above example by giving him the possibility of not worrying about the execution of caching clearance methods, but he is still responsible for the implementation of caching itself: declaration of the caching variable area, its initialization, and clearance.

Declarative Object Property Caching

The refreshable object library allows programmers to avoid defining caching variables and programming use of them. It is sufficient to mark getters requiring a cache with the @Cached annotation. In this case, all the caching and clearance procedures are made on the level of refreshable object mechanism, and the above example takes the following simple form:

@Refreshable
public class CachePattern {
   public int getWidth(){
      ...
   }

   public int getHeight(){
      ...
   }

   @Cached
   public int getArea(){
      return getWidth()*getHeight();
   }

   public void setWidth(int width){
      ...
   }

   public void setHeight(int height){
      ...
   }
...

Conclusion

All caching peculiarity has beenremoved from the program code except annotations. It is the core purpose of the mechanism to deliver a programmer the from routine of programming different object property caching aspects and to keep the possibility to define what properties to cache in a declarative manner. As a result, the main code contains application logic only; it easily can be read and modified. Programmer mistakes connected with caching mechanism implementation are reduced to a minimum.

The article illustrates features of the refreshable object library in the simple example for more clarity. The library itself is oriented on usage in a complex environment with many arbitrary interrelations among object properties.

A more detailed description of refreshable object principles is given at http://fusionsoft-online.com/refreshableobject.php. We would be glad to hear your remarks and opinion: info@fusionsoft-online.com.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read