4.2. Object mapping by reachability
A complex object by definition is an object that may consist of composite object references. Once a complex object is declared "prepared" (e.g., a Person object), during the putObject(Fqn fqn, Object pojo) operation, PojoCache will add a CacheInterceptor instance to the InstanceAdvisor associated with that object, as we have discussed above. In addition, the cache will map recursively the primitive object fields into the corresponding cache nodes.
The mapping rule is as follows:
Create a tree node using fqn, if not yet existed.
Go through all the fields (say, with an association java.lang.reflect.Field type field) in POJO,
If it is a primitive type, the field value will be stored under fqn with (key, value) pair of (field.getName(), field.getValue()). The following are primitive types supported now: String, Boolean, Double, Float, Integer, Long, Short, Character.
If it is a non-primitive type, creates a child FQN and then recursively executes another pubObject until it reaches all primitive types.
Following is a code snippet that illustrates this mapping process
for (Iterator i = type.getFields().iterator(); i.hasNext();) {
Field field = (Field) i.next();
Object value = field.get(obj);
CachedType fieldType = getCachedType(field.getType());
if (fieldType.isImmediate()) {
immediates.put(field.getName(), value);
} else {
putObject(new Fqn(fqn, field.getName()), value);
}
Let's take an example POJO class definition from the Appendix section where we have a Person object that has composite non-primitive types (e.g., List and Address). After we execute the putObject call, the resulting tree node will schematically look like the cache node in the following figures:
Person joe = new Person();
joe.setAddress(new Address());
cache.putObject("/aop/joe", joe);
The PojoCache APIs will be explained in fuller details later. But notice the illustration of object mapping by reachability in the following figure. The fqn /aop/joe is associated with the POJO joe. Then under that fqn, there are three children nodes: addr,skills, and languages. If you look at the Person class declaration, you will find that addr is an Address class, skills is a Set , and languages is a List type. Since they are non-primitive, they are recursively inserted under the parent object (joe) until all primitive types are reached. In this way, we have broken down the object graph into a tree view which fit into our internal structure nicely. Also note that all the primitive types will be stored inside the respective node's HashMap (e.g., addr will have Zip , Street , etc. stored there).
Here is a code snippet to demonstrate the object mapping by reachability feature that we just explained. Notice how a Person object (e.g., joe) that has complex object references will be mapped into the underlying cache store as explained above.
import org.jboss.cache.PropertyConfigurator;
import org.jboss.cache.aop.PojoCache;
import org.jboss.test.cache.test.standAloneAop.Person;
import org.jboss.test.cache.test.standAloneAop.Address;
PojoCache tree = new PojoCache();
PropertyConfigurator config = new PropertyConfigurator(); // configure tree cache.
config.configure(tree, "META-INF/replSync-service.xml");
Person joe = new Person(); // instantiate a Person object named joe
joe.setName("Joe Black");
joe.setAge(31);
Address addr = new Address(); // instantiate a Address object named addr
addr.setCity("Sunnyvale");
addr.setStreet("123 Albert Ave");
addr.setZip(94086);
joe.setAddress(addr); // set the address reference
tree.startService(); // kick start tree cache
tree.putObject("/aop/joe", joe); // add aop sanctioned object (and sub-objects) into cache.
// since it is aspectized, use of plain get/set methods will take care
// of cache contents automatically.
joe.setAge(41);
Note that a typical PojoCache usage involves instantiating the PojoCache , configuring, and starting the cache instance. Then, a user creates the aspectized POJO that will be put into the cache using putObject() API.
In addition, PojoCache also supports get/set with parameter type of some Collection classes (i.e., List , Map , and Set ) automatically. For example, the following code snippet in addition to the above example will trigger PojoCache to manage the states for the Languages list as well. The following figure illustrates the node structure from the replicated GUI point of view. Details of Collection class support will be given later.
ArrayList lang = new ArrayList();
lang.add("Ensligh");
lang.add("Mandarin");
joe.setLanguages(lang);