Value Object Wizard

The Wizard to materialize any value object and cache it

The Value Object Wizard (VOWizard or VOW in short) is very useful to manage the creation of value objects in an application.

BACKGROUND

The majority of the web applications in the world exist to display data of some form or the other. In vast enterprise portals (and to a lesser extent in other applications) the data is available in multiple disparate systems which are often unrelated to each other.

There may exist a canonical data model in the enterprise that might attempt to unify all this data available from various SOA calls into an object graph. But more often than not this model is conspicuous by its absence. Even if it exists, it tends to get extremely hairy to navigate for the average web  application which is often bothered only about a fraction of this potentially gigantic object graph. Hence most web applications tend to reckon with data only in the form of value objects or Data Transfer Objects (DTO). These objects are typically returned from various web services in the enterprise. VOs can also potentially be manufactured in the data base.

Further, many popular customer facing web sites in banks, telecom companies, insurance companies etc. tend to be a collection of "portlets". It is hard to share data across them without writing code that assumes the sequence of execution of the portlets, the APIs that they all would need etc. For instance, it is possible that portlet A requires customer information and portlet B also may need the exact same information. Both these portlets may have to be displayed in the Customer landing page. How do we ensure that two identical web service calls are not made to fetch the same customer data from both the portlets? Many times we see code that actually makes the call to the web service from Portlet A and passes it along to portlet B so that B does not need to make the exact same call. This kind of design is flaky since it would need to be re-factored if portlet A does not need the customer information anymore. Or for all we know, portlet A may even be removed from the landing page due to a user requirement. What happens then? Who makes the web service call? What is portlet C needs the same data too?

Here is where VOWizard comes in handy.

CODE SAMPLE

Before we delve into the solution, let us consider a simple code sample which would illustrate the utility of VOWizard.

Consider the code snippets below:

In portlet A

CustomerInformation customerInformation = ... // execute some code to obtain the customer information.
          
          // do something with the obtained customer information.
In portlet B
          
          CustomerInformation customerInformation = .. // either execute the same code to obtain customer information or // leverage the fact that portlet A has already
          
          //obtained this information  and start using this from a "cache"

With the Value Object wizard the code would become like this. In initialization:

VOWizardImpl vow = new VOWizardImpl();
          
          XmlVOConfigurator voc = new XmlVOConfigurator();
          
          voc.setFilename("somefile.xml"); // somefile.xml would contain the requisite xml configurations.
          
          vow.setVOConfigurator(voc);
          
          // All the stuff above would be done during start up
//   In portlet A
          
          CustomerInformation customerInformation = vow.getVO("customerInformation", requestInformationForMakingVO);
          
          //In portlet B
          
          // the code would be identical.

The advantage is that the VO would be cached and managed by the VOWizard.

Flexible Target Action

All value  objects are made by an implementation of VOAction. The VOAction may contain any code as desired to fetch the information from the back end store.

Interceptors

Before the action is called the VOWizard invokes a configured set of interceptors which have the opportunity to respond to the request or pass it upstream.

Caching Implementation

VOWizard ships with both L1 and L2 caching interceptors. EHCache is used by the L2 interceptor while the L1 interceptor is capable of storing the retrieved data in a more ephemeral object such as request or session.

Identity Management

The VOWizard caches support the notion of identity management. Value objects can have multiple keys by which they can be queried. The request objects used to obtain the value objects

Object Graph Support

The VOWizard supports the notion of a domain model for the value objects. Example: Let us say we have a customer  object which in turn is linked to multiple Account objects. The customer object is attached to a session. If we need to retrieve the account details then the customer object must first be retrieved from the session. Then the account information is retrieved from the customer object. If we query for an account, the  VOWizard  would materialize the entire tree of objects in the session. The customer object is created and the retrieved account object is attached to it. This is supported to an arbitrary depth. See the test case for more details.

Centralized Configuration

The interceptors and the actions for every object are configured centrally. XML is currently supported. This enables a separation of concerns between the architect who can configure the wizard and the developers who can write the action to retrieve value objects from the back end systems.

Class Diagram

The class diagram above depicts the classes involved in the framework. As is evident from a cursory inspection, the framework itself is extremely simple and extensible.

The green parts constitute the core framework while the brick colored parts constitute the various action implementations that have been shipped out of the box.

VOWizard is the interface with the VOWizardImpl being the implementation. This is the class that you start off with. VOWizard has a getVO() and update() methods which respectively take care of retrieving and updating the VO. The client invokes one of the methods. Both these methods use  a configuration information for deciding what to do in the process of retrieving or updating the VO in question.

They call the obtainVO() or update() methods respectively for a series of VO filters which need to be explicitly configured for every VO. The chain culminates in a VOAction whose obtainVO() or update() VO is called.

The VOFilters are passed a VOFilterChain as a parameter while the VOAction is not passed the chain. This is because the VOFilters have the ability to continue the chain or terminate it if they are able to return the result.

All configurations are stored and made available by an instance of VOConfigurator that VOWizardImpl consults. An instance of VOConfigurator called XmlVOCOnfigurator is shipped along with the VOWizard. All configurations are stored in the form of VODescriptor objects which are in turn chained to other descriptor objects as shown in the diagram.