JPOX
JPOX
 Project  |  Ver 1.1  |  Ver 1.2  |  JDO  |  JPA  |  Guides  |  Tools
1.2 | Persistence | JDO ORM | JPA ORM | Runtime | JDO Runtime | JPA Runtime | Extensions | Developer
JPOX Runtime
RDBMS Datastores
DB4O Datastore
JPOX Caching

Caching is an essential mechanism in providing efficient usage of resources in many systems. JDO is no different and provides a definition of caching at 2 levels. Caching allows objects to be retained and returned rapidly without having to make an extra call to the datastore. JPOX provides a facility for caching that meets the specification, but in addition allows the use of third party caching tools (such as Tangosol Coherence, EHCache, OSCache, etc) for the level 2 caching (and also allows user-defined Level2 caches).

The 2 levels of caching available with JPOX are

  • Level 1 Cache - this is mandated by the JDO specification, and represents the caching of JDO instances within a PersistenceManager.
  • Level 2 Cache - this represents the caching of JDO instances within a PersistenceManagerFactory (across multiple PersistenceManager's)

You can think of a cache as a Map, with values referred to by keys. In the case of JDO, and of JPOX, the value is the PersistenceCapable object and the key is the object identity. Since identity is unique in JDO, the keys refer to unique objects.







Caching Support - Level 1

By default in JPOX, Level 1 Cache is enabled. You cannot turn off the Level 1 Cache. There are inbuilt types for the Level 1 Cache available for selection.

JPOX supports the following types of Level 1 Cache.

  • weak - uses a weak reference backing map. If JVM garbage collection clears the reference, then the object is removed from the cache. This is the default Level 1 Cache
  • soft - uses a soft reference backing map. If the map entry value object is not being actively used, then garbage collection may garbage collect the reference, in which case the object is removed from the cache.
  • hard - uses a normal HashMap backing. With this option all references are strong meaning that objects stay in the cache until they are explicitly removed by calling remove() on the cache.

You can specify the type of Level 1 Cache by providing the PMF property org.jpox.cache.level1.type. You set this to the value of the type required. If you want to remove objects from the L1 cache programmatically you should use pm.evict() or pm.evictAll().

Caching Support - Level 2

By default in JPOX, Level 2 Cache is disabled. The user can configure the Level 2 Cache if they so wish. This is controlled by use of the PersistenceManagerFactory property org.jpox.cache.level2 which is a boolean property and turns on/off the use of the Level 2 Cache. There are inbuilt default types of Level 1 and Level 2 caching in JPOX.

With the Level 2 Cache you currently have the following options.

  • org.jpox.cache.DefaultLevel2Cache - the default option. Provides support for the JDO 2 interface of being able to pin objects into the cache, and unpin them when required. This option does not support distributed caching, solely running within the JVM of the client application. Weak references are held to non pinned objects.
  • org.jpox.cache.SoftLevel2Cache - Provides support for the JDO 2 interface of being able to pin objects into the cache, and unpin them when required. This option does not support distributed caching, solely running within the JVM of the client application. Soft references are held to non pinned objects.
  • org.jpox.cache.EhcacheLevel2Cache - a simple wrapper to EHCache's caching product. Provides basic support for adding items to the cache and retrieval from the cache. Doesn't support pinning and unpinning.
  • org.jpox.cache.OSCacheLevel2Cache - a simple wrapper to OSCache's caching product. Provides basic support for adding items to the cache and retrieval from the cache. Doesn't support pinning and unpinning.
  • org.jpox.cache.SwarmCacheLevel2Cache - a simple wrapper to SwarmCache's caching product. Provides basic support for adding items to the cache and retrieval from the cache. Doesn't support pinning and unpinning.
  • org.jpox.cache.TangosolLevel2Cache - a simple wrapper to Tangosol's Coherence caching product. Provides basic support for adding items to the cache and retrieval from the cache. Doesn't support pinning and unpinning. Tangosol's caches support distributed caching, so you could, in principle, use JPOX in a distributed environment with this option.

You can specify the type of Level 2 Cache by providing the PMF property org.jpox.cache.level2.type. You set this to the value of the type required. In JPOX up to 1.1.1 you would specify the class name shown above. In JPOX 1.1.2 and onwards you can specify "DEFAULT", "SOFT", "EHCache", "EHCacheClassBased", "OSCache", "SwarmCache" or "Tangosol".

If we do not have support for a particular third party caching product, you can easily extend an interface org.jpox.cache.Level2Cache to provide support. If you do this for a product that we don't have a plugin for, why not contribute it so we can include it in a future release ?



Utilising the Cache

The majority of times when using a JDO-enabled system you will not have to take control over any aspect of the caching other than specification of whether to use a Level 2 Cache or not. With JDO 2 and with JPOX 1.1 you have the ability to control which objects remain in the cache. This is available via a method on the PersistenceManagerFactory.

PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props);
DataStoreCache cache = pmf.getDataStoreCache();

The DataStoreCache interface provides methods to control the retention of objects in the cache. You have 3 groups of methods

  • evict - used to remove objects from the Level 2 Cache
  • pin - used to pin objects into the cache, meaning that they will not get removed by garbage collection, and will remain in the Level 2 cache until removed.
  • unpin - used to reverse the effects of pinning an object in the Level 2 cache. This will mean that the object can thereafter be garbage collected if not being used.

These methods can be called to pin objects into the cache that will be much used. Clearly this will be very much application dependent, but it provides a mechanism for users to exploit the caching features of JDO. If an object is not "pinned" into the L2 cache then it can typically be garbage collected at any time, so you should utilise the pinning capability for objects that you wish to retain access to during your application lifetime. For example, if you have an object that you want to be found from the cache you can do

PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props);
DataStoreCache cache = pmf.getDataStoreCache();
cache.pinAll(MyClass.class, false); // Pin all objects of type MyClass from now on
PersistenceManager pm = pmf.getPersistenceManager();
Transaction tx = pm.currentTransaction();
try
{
    tx.begin();

    pm.makePersistent(myObject);
    // "myObject" will now be pinned since we are pinning all objects of type MyClass.

    tx.commit();
}
finally
{
    if (tx.isActive())
    {
    	tx.close();
    }
}

Thereafter, whenever something refers to myObject, it will find it in the Level 2 cache. To turn this behaviour off, the user can either unpin it or evict it.

If an object is in the Level 2 cache and it is updated, these updates will also be stored in the Level 2 cache. Similarly if you have an object in the Level 2 cache which has some fields that haven't been loaded (due to not being in the FetchPlan for example), then any loading of these fields will also result in the object in the L2 cache being updated.



Tangosol Coherence plugin

As mentioned above, JPOX provides a simple wrapper to Tangosol's Coherence caches. This currently takes the NamedCache interface in Tangosol and instantiates a cache of a user provided name. To enabled this you should set the following properties as input to the PersistenceManagerFactory

org.jpox.cache.level2=true
org.jpox.cache.level2.type=tangosol
org.jpox.cache.level2.cacheName={tangosol cache name}

The Tangosol cache name is the name that you would normally put into a call to CacheFactory.getCache(name). As mentioned earlier, this cache does not support the pin/unpin operations found in the standard JDO 2 interface. However you do have the benefits of Tangosol's distributed/serialized caching. If you require more control over the Tangosol cache whilst using it with JPOX, you can just access the Tangosol cache directly via

DataStoreCache cache = pmf.getDataStoreCache();
NamedCache tangosolCache = ((TangosolLevel2Cache)cache).getTangosolCache();
EHCache plugin

As mentioned above, JPOX provides a simple wrapper to EHCache's caches. To enable this you should set the following properties as input to the PersistenceManagerFactory

org.jpox.cache.level2=true
org.jpox.cache.level2.type=ehcache
org.jpox.cache.level2.cacheName={cache name}
org.jpox.cache.level2.configurationFile={EHCache configuration file resource path (must be in classpath)}

The EHCache plugin also provides an alternatvie L2 Cache that is class-based. To use this you would need to replace "ehcache" above with "ehcacheclassbased".

See also :-

OSCache plugin

As mentioned above, JPOX provides a simple wrapper to OSCache's caches. To enable this you should set the following properties as input to the PersistenceManagerFactory

org.jpox.cache.level2=true
org.jpox.cache.level2.type=oscache
org.jpox.cache.level2.cacheName={cache name}

See also :-

SwarmCache plugin

As mentioned above, JPOX provides a simple wrapper to SwarmCache's caches. To enable this you should set the following properties as input to the PersistenceManagerFactory

org.jpox.cache.level2=true
org.jpox.cache.level2.type=swarmcache
org.jpox.cache.level2.cacheName={cache name}

See also :-