In this section, we will discuss an overview of the PojoCache APIs including the PojoCacheFactory class.
PojoCacheFactory provides couple of static methods to instantiate and obtain a PojoCache instance.
/** * Create a PojoCache instance. Note that this will start the cache life cycle automatically. * @param config A configuration string that represents the file name that is used to * configure the underlying Cache instance. * @return PojoCache */ public static PojoCache createInstance(String config); /** * Create a PojoCache instance. * @param config A configuration string that represents the file name that is used to * configure the underlying Cache instance. * @param start If true, it will start the cache life cycle. * @return PojoCache */ public static PojoCache createInstance(String config, boolean start); /** * Create a PojoCache instance. * @param config A configuration object that is used to configure the underlying Cache instance. * @param start If true, it will start the cache life cycle. * @return PojoCache */ public static PojoCache createInstance(Configuration config, boolean start);
For example, to obtain a PojoCache instance and start the cache lifestyle automatically, we can do:
String configFile = "META-INF/replSync-service.xml"; PojoCache cache = PojoCacheFactory.createInstance(configFile);
In PojoCache, there are 3 core APIs for pojo management and one additional one for querying. They will be fully discussed here. Note that we have stressed that the management aspect of these APIs. This is because we expect most of the time, you only use these APIs to attach, detach, and retrieve the POJO from the cache system. After that, a user should operate on that POJO reference directly without worrying about replication and/or persistency aspects.
/** * Attach a POJO into PojoCache. It will also recursively put any sub-POJO into * the cache system. A POJO can be the following and have the consequences when attached: * * It is PojoCacheable, that is, it has been annotated with * {@see org.jboss.cache.aop.annotation.PojoCacheable} annotation (or via XML), and has * been "instrumented" either compile- or load-time. The POJO will be mapped recursively to * the system and fine-grained replication will be performed. * * It is Serializable. The POJO will still be stored in the cache system. However, it is * treated as an "opaque" object per se. That is, the POJO will neither be intercepted * (for fine-grained operation) or object relationship will be maintained. * * Neither of above. In this case, a user can specify whether it wants this POJO to be * stored (e.g., replicated or persistent). If not, a PojoCacheException will be thrown. * * @param id An id String to identify the object in the cache. To promote concurrency, we * recommend the use of hierarchical String separating by a designated separator. Default * is "/" but it can be set differently via a System property, jbosscache.separator * in the future release. E.g., "ben", or "student/joe", etc. * @param pojo object to be inserted into the cache. If null, it will nullify the fqn node. * @return Existing POJO or null if there is none. * @throws PojoCacheException Throws if there is an error related to the cache operation. */ Object attach(String id, Object pojo) throws PojoCacheException;
Calling this Api will put your POJO into the cache management under id String. The pojo is the object instance to be managed by PojoCache.
The requirement for pojo is that it must have been instrumented or implement the Serializable interface. An object is instrumented by JBossAop if declared either from an xml file or from annotation. More details on this will come later.
When the POJO is only serializable, PojoCache will simply treat it as an opaque "primitive" type. That is, it will simply store it without mapping the object's field into cache. Replication is done on the object wide level and therefore no fine-grained replication can be obtained.
If pojo has sub-objects, e.g., it has fields that are non-primitive type, this call will issue attach recursively until all object tree are traversed (mapping by reachability). In addition, if you put pojo in multiple times, it will simply returns the original object reference right away. Furthermore, if this POJO has been referenced multiple times, e.g., referenced from other POJO or circular reference, this Api will handle the appropriate reference counting.
The return value after the call is the existing object under fqn (if any). As a result, a successful call will replace that old value with pojo instance, if it exists. Note that a user will only need to issue this call once for each POJO (think of it as attaching POJO to cache management). Once it is executed, PojoCache will assign an interceptor for the pojo instance and its sub-objects.
/** * Remove POJO object from the cache. * * @param id Is string that associates with this node. * @return Original value object from this node. * @throws PojoCacheException Throws if there is an error related to the cache operation. */ Object detach(String id) throws PojoCacheException;
This call will detach the POJO from the cache management by removing the contents under id and return the POJO instance stored there (null if it doesn't exist). After successfully call, any POJO operation on the returned POJO reference is not intercepted by the cache system anymore. So in essence, you will use this Api should you decide that the POJO under fqn is no longer necessary. For example, if a POJO is no longer in context, you will need explicitly invoke this Api otherwise it won't get garbage collected by the VM. Note this call will also remove everything stored under id even if you have put other plain cache data there.
/** * Retrieve POJO from the cache system. Return null if object does not exist in the cache. * Note that this operation is fast if there is already a POJO instance attached to the cache. * * @param id that associates with this node. * @return Current content value. Null if does not exist. * @throws PojoCacheException Throws if there is an error related to the cache operation. */ Object find(String id) throws PojoCacheException;
This call will return the current object content located under id. This method call is useful when you don't have the exact POJO reference. For example, when you fail over to the replicated node, you want to get the object reference from the replicated cache instance. In that case, PojoCache will create a new Java object if it does not exist and then add the cache interceptor such that every future access will be in sync with the underlying cache store.
/** * Query all managed POJO objects under the id recursively. Note that this will not return * the sub-object POJOs, e.g., if Person has a sub-object of Address, it * won't return Address pojo. Also note also that this operation is not thread-safe * now. In addition, it assumes that once a POJO is found with a id, no more POJO is stored * under the children of the id. That is, we don't mix the id with different POJOs. * * @param id The starting place to find all POJOs. * @return Map of all POJOs found with (id, POJO) pair. Return size of 0, if not found. * @throws PojoCacheException Throws if there is an error related to the cache operation. */ Map findAll(String id) throws PojoCacheException;
This call will return all the managed POJOs under cache with a base Fqn name. It is recursive, meaning that it will traverse all the sub-trees to find the POJOs under that base. For example, if you specify the fqn to be root, e.g., "/" , then it will return all the managed POJOs under the cache.
Note also that this operation is currently not thread-safe. In addition, it assumes that once a pojo is found with a fqn, no more pojo is stored under the children of the fqn. That is, we don't mixed the fqn with different POJOs.