Apache Commons logo

Commons JCS™

Getting Started

To start using JCS you need to (1) understand the core concepts, (2) download JCS, (3) get the required dependencies, (4) configure JCS, and (5) then start programming to it. The purpose of the getting started guide is to help you get up and running with JCS as quickly as possible. In depth documentation on the various features of JCS is provided in the User's Guide.

STEP 1: Understand the Core Concepts

In order to use JCS, you must understand a few core concepts, most importantly you need to know the difference between "elements," "regions," and "auxiliaries".

JCS is an object cache. You can put objects, or "elements," into JCS and reference them via a key, much like a hashtable.

You can think of JCS as a collection of maps that you reference by name. Each of these maps is called a "region," and each region can be configured independently of the others. For instance, I may have a region called Cities where I cache City objects that change infrequently. I may also define a region called Products where I cache product data that changes more frequently. I would configure the volatile Product region to expire elements more quickly than the City region.

"Auxiliaries" are optional plugins that a region can use. The core auxiliaries are the Indexed Disk Cache, the TCP Lateral Cache, and the Remote Cache Server. The Disk Cache, for example, allows you to swap items onto disk when a memory threshold is reached. You can read more about the available auxiliaries HERE .

STEP 2: Download JCS

Download the latest version of JCS. The latest JCS builds are located HERE

If you would like to build JCS yourself, check it out from Subversion and build it as you would any other project built by Maven. The location of the repository is documented in the project info pages that are linked via the left nav.

STEP 3: Get the Required Dependencies

Beginning with version 2.0 the core of JCS (the LRU memory cache, the indexed disk cache, the TCP lateral, and the RMI remote server) requires only commons-logging.

Beginning with version 1.2.7.0 and up to version 1.3, the core of JCS (the LRU memory cache, the indexed disk cache, the TCP lateral, and the RMI remote server) requires only two other jars.

concurrent

commons-logging

Versions 1.2.6.9 and below also require the following two additional jars:

commons-collections

commons-lang

All of the other dependencies listed on the project info page are for optional plugins.

STEP 4: Configure JCS

JCS is configured from a properties file called "cache.ccf". There are alternatives to using this file, but they are beyond the scope of the getting started guide.

The cache configuration has three parts: default, regions, and auxiliaries. You can think of the auxiliaries as log4j appenders and the regions as log4j categories. For each region (or category) you can specify and auxiliary (or appender to use). If you don't define a region in the cache.ccf, then the default settings are used. The difference between JCS and log4j is that in JCS, pre-defined regions do not inherent auxiliaries from the default region.

The following cache.ccf file defines one region called "testCache1" and uses the Indexed Disk Cache, here called "DC" by default. The LRU Memory Cache is selected as the memory manager.

                
# DEFAULT CACHE REGION
jcs.default=DC
jcs.default.cacheattributes=org.apache.commons.jcs3.engine.CompositeCacheAttributes
jcs.default.cacheattributes.MaxObjects=1000
jcs.default.cacheattributes.MemoryCacheName=org.apache.commons.jcs3.engine.memory.lru.LRUMemoryCache
jcs.default.cacheattributes.UseMemoryShrinker=false
jcs.default.cacheattributes.MaxMemoryIdleTimeSeconds=3600
jcs.default.cacheattributes.ShrinkerIntervalSeconds=60
jcs.default.elementattributes=org.apache.commons.jcs3.engine.ElementAttributes
jcs.default.elementattributes.IsEternal=false
jcs.default.elementattributes.MaxLife=21600
jcs.default.elementattributes.IdleTime=1800
jcs.default.elementattributes.IsSpool=true
jcs.default.elementattributes.IsRemote=true
jcs.default.elementattributes.IsLateral=true

# PRE-DEFINED CACHE REGIONS
jcs.region.testCache1=DC
jcs.region.testCache1.cacheattributes=org.apache.commons.jcs3.engine.CompositeCacheAttributes
jcs.region.testCache1.cacheattributes.MaxObjects=1000
jcs.region.testCache1.cacheattributes.MemoryCacheName=org.apache.commons.jcs3.engine.memory.lru.LRUMemoryCache
jcs.region.testCache1.cacheattributes.UseMemoryShrinker=false
jcs.region.testCache1.cacheattributes.MaxMemoryIdleTimeSeconds=3600
jcs.region.testCache1.cacheattributes.ShrinkerIntervalSeconds=60
jcs.region.testCache1.cacheattributes.MaxSpoolPerRun=500
jcs.region.testCache1.elementattributes=org.apache.commons.jcs3.engine.ElementAttributes
jcs.region.testCache1.elementattributes.IsEternal=false

# AVAILABLE AUXILIARY CACHES
jcs.auxiliary.DC=org.apache.commons.jcs3.auxiliary.disk.indexed.IndexedDiskCacheFactory
jcs.auxiliary.DC.attributes=org.apache.commons.jcs3.auxiliary.disk.indexed.IndexedDiskCacheAttributes
jcs.auxiliary.DC.attributes.DiskPath=${user.dir}/jcs_swap
jcs.auxiliary.DC.attributes.MaxPurgatorySize=10000000
jcs.auxiliary.DC.attributes.MaxKeySize=1000000
jcs.auxiliary.DC.attributes.OptimizeAtRemoveCount=300000
jcs.auxiliary.DC.attributes.ShutdownSpoolTimeLimit=60

            

Basic JCS configuration is described in more detail HERE

Element level configuration is described in more detail HERE

For more information on advanced configuration options and the available plugins, see the User's Guide.

STEP 5: Programming to JCS

JCS provides a few convenient classes that should meet all your needs.

To get a cache region you simply ask JCS for the region by name. If you wanted to use JCS for City objects, you would do something like this:

                
import java.io.Serializable;
import org.apache.commons.jcs3.JCS;
import org.apache.commons.jcs3.access.CacheAccess;
import org.apache.commons.jcs3.access.exception.CacheException;

public class JcsExample 
{
    public static void main( String[] args ) 
    {
        JcsExample example = new JcsExample();
        example.testCache();
    }

    private CacheAccess<String, City> cache = null;

    public JcsExample() 
    {
        try 
        {
            cache = JCS.getInstance( "default" );
        }
        catch ( CacheException e ) 
        {
            System.out.println( String.format( "Problem initializing cache: %s", e.getMessage() ) );
        }
    }

    public void putInCache( City city ) 
    {
        String key = city.name;
        try 
        {
            cache.put( key, city );
        }
        catch ( CacheException e ) 
        {
            System.out.println( String.format( "Problem putting city %s in the cache, for key %s%n%s",
                    city.name, key, e.getMessage() ) );
        }
    }

    public City retrieveFromCache( String cityKey ) 
    {
        return cache.get( cityKey );
    }

    public void testCache() 
    {
        City zurich = new City( "Zürich", "Switzerland", 366765 );
        putInCache( zurich );
        
        City berlin = new City( "Berlin", "Germany", 3502000 );
        putInCache( berlin );
        
        City johannesburg = new City( "Johannesburg", "South Africa", 12200000 );
        putInCache( johannesburg );

        City retrievedCity1 = retrieveFromCache( "Berlin" );
        if ( retrievedCity1 != null ) 
        {
            System.out.println( retrievedCity1.toString() );
        }
        else 
        {
            System.out.println( "No object was found in the cache for the key \"Berlin\"" );
        }

        City retrievedCity2 = retrieveFromCache( "New York" );
        if ( retrievedCity2 != null ) 
        {
            System.out.println( retrievedCity2.toString() );
        }
        else 
        {
            System.out.println( "No object was found in the cache for the key \"New York\"" );
        }
    }

    // defined as a nested inner class to reduce number of .java files in the example
    public class City implements Serializable 
    {
        private static final long serialVersionUID = 6392376146163510146L;
        public String name;
        public String country;
        public int population;

        public City( String name, String country, int population ) 
        {
            this.name = name;
            this.country = country;
            this.population = population;
        }

        @Override
        public String toString() 
        {
            return String.format( "%s is a city in the country %s with a population of %d", name, country, population );
        }
    }
}