YOUR FEEDBACK
wrote: Trackback Added: Who is Technology’s Highest Paid CEO?; Who is Technology&...


2008 East
DIAMOND SPONSOR:
Data Direct
Frontiers in Data Access: The Coming Wave in Data Services
PLATINUM SPONSORS:
Red Hat
The Opening of Virtualization
Intel
Virtualization – Path to Predictive Enterprise
Green Hills
IT Security in a Hostile World
JBoss / freedom oss
Practical SOA Approach
GOLD SPONSORS:
Software AG
The Art & Science of SOA: How Governance Enables Adoption
PlateSpin
Effective Planning for Virtual Infrastructure Growth
Fujitsu
Automated Business Process Discovery & Virtualization Service
Ceedo
Workspace Virtualization
Click For 2007 West
Event Webcasts

2008 East
PLATINUM SPONSORS:
Appcelerator
Think Fast: Accelerate AJAX Development with Appcelerator
GOLD SPONSORS:
DreamFace Interactive
The Ultimate Framework for Creating Personalized Web 2.0 Mashups
ICEsoft
AJAX and Social Computing for the Enterprise
Kaazing
Enterprise Comet: Real–Time, Real–Time, or Real–Time Web 2.0?
Nexaweb
Now Playing: Desktop Apps in the Browser!
Sun
jMaki as an AJAX Mashup Framework
POWER PANELS:
The Business Value
of RIAs
What Lies Beyond AJAX?
KEYNOTES:
Douglas Crockford
Can We Fix the Web?
Anthony Franco
2008: The Year of the RIA
Click For 2007 Event Webcasts
SYS-CON.TV
TOP THREE LINKS YOU MUST CLICK ON


Proxy Cache
A practical implementation

A proxy cache is a behavioral technique that provides the ability to cache a result-set (output) from a service call via a proxy using the argument-set (input) as the cache key. Through this proxy, all calls to any concrete instances of a defined type, service, are made. In this proxy, input is used as the key to obtain from or provide to a cache the output from a called service. If output has already been cached for a given input, the proxy returns the cached output without forwarding the call to the actual service.

This article presents a software design approach that will allow you to add a transparent caching layer to your applications. This approach will work for all types of applications (middle-tier, client-side, batch, etc.) under many scenarios (Web services, database access, etc.).

Although this article does refer to caching, it's not about caching. Instead, this article attempts to provide a description of how to incorporate a feature, such as caching, modularly and without major impact to existing code.

Provided first is a description of how my colleagues and I ended up at a proxy cache and is followed by a generic summary of how to design and implement a proxy cache solution.

Background
While working with several colleagues on a recent project, we decided to avoid any performance problems that were caused by repeatedly retrieving data from our back-end data store and from the performance problems related to object creation when generating responses from the services in our service layer. To accomplish this, we needed to incorporate a cache mechanism into that service layer.

The service layer was fairly simple in that most of the services were read-only with some basic business logic applied behind the scenes. We were not using any object/relational (O/R) mapping tools, just basic Data Access Objects (DAOs) and, therefore, several ideas were tossed around.

One idea was to simply use an O/R tool. Any good O/R tool would include a caching mechanism to avoid hitting the database unnecessarily. However, we decided against this for a couple of reasons:

  • Previous and bad experiences with a commercial O/R tool specifically related to caching and synchronization.
  • A motivating drive to keep things as simple as can be, but no simpler.
  • It did not solve the problem related to object creation.
Another idea was to utilize a third-party caching solution. Although there are many to choose from, they did not address all of our software design concerns. We therefore realized that we needed to define some objectives for our caching system. These objectives are defined below:
  • The caching system should be transparent to the user and the used.
  • The caching system should eliminate the sprinkling of cache code throughout the code base, i.e., to implement caching in a single place so as not to violate the Single Responsibility Principle (SRP) and Once And Only Once (OAOO) concept.
In addition, many of the third-party systems were fairly heavyweight, requiring more configuration than we desired and a fair amount of physical space for the library or libraries. We were not strictly opposed to using these tools, but we needed something else first.

Another viable option for us was to introduce caching code into each service, but this was not suitable either as it violated some of our principles. The SRP was violated when the service would have been responsible for its normal, expected behavior and also caching.

OAOO was violated when we would have had to introduce the same code into each service. We could have abstracted the behavior into a base class or supporting utility class, but SRP would still have been violated, so why bother.

Proxy Cache
After some consideration, we realized that we were saying we wanted an aspect of caching applied to each of our services. The role of this aspect would be to (1) check a cache to determine if the service had already been called with the provided input and if so, would (2) return the cached output or else it would (3) complete the call and then cache the output.

Java does not have extensive built-in support for Aspect-Oriented Programming, and we did not want to introduce an AOP extension such as AspectJ. However, Java does provide built-in support for proxies via the dynamic proxy class (proxy class), provided by the standard Java platform since JDK1.3. A proxy class could be used to encapsulate our needed behavior without violating our core principles and making us feel all "dirty." From this idea was born our concept of a proxy cache.

Note: The choice to not use an O/R mapping tool does not negate using one in the future. You could potentially use a proxy cache and an O/R mapping tool concurrently.

Dynamic Proxy
At the heart of the proxy cache technique is the Proxy pattern. If you are not familiar with what the Proxy Pattern is, the accepted definition is that a proxy "[provides] a surrogate or placeholder for another object to control access to it." The goal of the proxy cache is to be a surrogate to the service, but with a small caveat that it must also be able to present itself as the actual service, such that the caller of the service cannot differentiate the two. The proxy cache for a given service must be able to stand-in for the service itself.

In Java, there are obviously many ways that a proxy can be implemented, but this article will utilize the well-established proxy class, java.lang.reflect.Proxy. Using a proxy class will allow the proxy cache to disguise itself as the service without implementing any user-defined interfaces.

The basic protocol for using the proxy class is as follows:

  1. Provide an implementation of java.lang.reflect.InvocationHandler.
  2. Generate a new proxy instance by providing a classloader, an array of interfaces the proxy shall implement, and an instance of your invocation handler.
  3. Cast the proxy object to a type consistent with the interfaces you provided when generating the proxy.
Below is an example of the implementation of this protocol:

InvocationHandler handler =
   new FooInvocationHandler(new Bar());
Foo f = (Foo) Proxy.newProxyInstance(
     Foo.class.getClassLoader(),
     new Class[]{ Foo.class }, handler);

In your invocation handler you are required to implement an invoke() method that must accept the proxy instance, a reference to the method that is being called on that instance, and any arguments that are being passed to that instance. In this invoke() method you can provide an epilogue and/or prologue to the actual method call; i.e., you can "wrap" the intended method call with your own custom behavior.

The invocation handler must also have access to a concrete instance of the desired object. This is perhaps the trickiest aspect of the proxy class framework as it requires a priori knowledge of the caller's intentions or a very specific implementation of an invocation handler. In the case of the proxy cache, the most useful implementation is to pass the concrete object as an argument to the constructor of the invocation handler. This, however, implies a bijectional relationship between the proxy and the proxied object, which may only be bad if there is an explosion of objects needing a proxy.

Implementing a Proxy Cache
In general, we would like to limit the number of places where proxy cache is actually referenced; therefore, the most basic way to implement proxy cache is through a factory or builder. A factory is used to isolate the details of generating a new service. Isolating these details is important because our ServiceFactory will be responsible for generating concrete service instances, generating invocation handler (CacheProxy) instances for services, and returning proxies to the services.

Shown in Figure 1 is a simple entity relationship diagram of the framework that will be implemented. Generally, you will already have everything shown in the diagram well established in your system except for CacheProxy. Why? Because you're not going to introduce a proxy cache until you actually need it. Introduce caching only when you know there is a problem. In Figure 1, all interfaces are illustrated as a rounded-rectangle.

As is shown, the Service interface knows only about itself:

package service;
public interface Service {
   public Object service(
     Object toService);
}

The CacheProxy class knows about the service and is an implementation of the InvocationHandler interface. Finally, the ServiceFactory knows about everything service related (including the Concrete Service, albeit implicitly).

Where does the caching behavior go? The responsibility of caching firmly belongs to CacheProxy. But, how is the CacheProxy created so that it may enable caching? Normally, the ServiceFactory would create a Concrete Service and basically return it. When utilizing proxy cache, ServiceFactory will still create the Concrete Service instance, but will pass that instance to a new instance CacheProxy and return the CacheProxy instance instead. Therefore, whenever a method is called on the service (even those not defined in the service interface), the call will be trapped by the CacheProxy, wherein a cache can be investigated prior to passing the call on to the Concrete Service.

About Justin Knowlden
Justin Knowlden is a solutions architect with United Airlines. Prior to United, he helped develop the MyPoints.com product from its inception. Justin is actively participating in the open source community (see Helium and ESP). When not programming he is a husband, a basketball and football coach for his son, and an environmental and animal rights activist.

LATEST JAVA STORIES & POSTS
An applet, a Java program that runs in a browser, often has to access the client resources. However, the security manager prevents an applet from accessing client resources. To access client resources, the applet has to have the proper permission. With this permission the applet ...
Three-letter acronyms (TLAs) are hardly new in Information Technology: EAI, ESB, SOA, BPM, BAM, ETL, MDM; the list goes on and on. This article is about yet another three-letter acronym, EDA, which stands for Event-Driven Architecture. EDA is not a brand new technology, but rathe...
Furthering its dedication to providing Java developers productivity with choice, Oracle announced the Oracle Enterprise Pack for Eclipse, a new component of Oracle Fusion Middleware. This release marks the first free Eclipse 3.4 environment to support Oracle WebLogic Server 10g R...
Two of the biggest launches in Rich Internet Application history took place in 2007/2008 when Adobe launched AIR 1.0 in February '08 and Microsoft launched Silverlight (September '07). At the 6th International AJAXWorld RIA Conference & Expo in October SYS-CON Events is delighted...
Red Hat CTO Brian Stevens, Citrix CTO Simon Crosby, Egenera CTO Pete Manca, Allen Stewart, Group Manager, Windows Virtualization at Microsoft, and Brian Duckering, Sr. Director of Products and Alliances at Symantec were the top industry executives who joined Jeremy Geelan in the ...
Government intervention and direction has long been critical to the development of the computer industry. The Internet, after all, was derived from the ARPANET, developed in the early 1970s from a U.S. government-sponsored research project by the Advanced Research Projects Agency...
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS
SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
Click to Add our RSS Feeds to the Service of Your Choice:
Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
Publish Your Article! Please send it to editorial(at)sys-con.com!

Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021


SYS-CON FEATURED WHITEPAPERS

SPONSORED BY INFRAGISTICS
There are many forces that influence technological evolution. After a decade of building enterprise ...
2008 is going to be an important year for Rich Internet Applications. Most organizations are deliver...
The OpenAjax Alliance is developing an Ajax industry wishlist for future browsers, using a dedicated...
In every field of design one of the first things students do is learn from the work of others. They ...
Infragistics announced the availability of two Community Technology Preview (CTP) User Interface (UI...
The YUI development team has released version 2.5.2; you can download the new release from SourceFor...
ADS BY GOOGLE
BREAKING JAVA NEWS

SpringSource, a leading provider of infrastructure software and the company behind ...