- fix inconsistent getCacheCheckFrequency time unit: set in global default cache service 
check frequency to milliseconds as expected (e.g. in calling wait and other services, fix CacheTest#getCacheRefresh).
- explain timetolive field has setter getTTL
- add example / allow optional disk cache usage test for jcs

git-svn-id: https://svn.apache.org/repos/asf/turbine/fulcrum/trunk/cache@1890338 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index ae7aada..32f2bcd 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -25,10 +25,14 @@
 

   <body>

     <release version="1.1.1" date="in subversion">

+         <action dev="gk" type="update">

+          Backward-incompatible change: Global default cache frequency setting is now in milliseconds, 

+          as already the ehcache and the JCS.

+       </action>

      <action dev="gk" type="update">

         - Test: Use tags to skip long running tests, minor fixes in log4j2 configuration and test assertion.

         - Update tests to JUnit 5 and dependencies to Fulcrum Testcontainer 1.0.9 and Turbine Parent 8

-        -  Updated EHCache to v2.10.9.2

+        -  Updated EHCache to v2.10.9.2.

        </action>

        <action dev="gk" type="update">

          Update JCS to commons-jcs3-core

diff --git a/src/java/org/apache/fulcrum/cache/CachedObject.java b/src/java/org/apache/fulcrum/cache/CachedObject.java
index 73dffd0..534d2f5 100644
--- a/src/java/org/apache/fulcrum/cache/CachedObject.java
+++ b/src/java/org/apache/fulcrum/cache/CachedObject.java
@@ -54,13 +54,13 @@
     private T contents = null;
 
     /** Default age (30 minutes). */
-    private final long defaultAge = 1_800_000;
+    private static final long DEFAULT_AGE = 1_800_000;
 
     /** When the object is created. */
-    protected long created = 0;
+    protected long created;
 
     /** When the object should expire. */
-    private long expires = 0;
+    private long expires;
 
     /** Is this object stale/expired? */
     private final AtomicBoolean stale = new AtomicBoolean();
@@ -71,7 +71,7 @@
      * @param object
      *            The object you want to cache.
      */
-    public CachedObject(T object)
+    public CachedObject(final T object)
     {
         this(object, DEFAULT);
     }
@@ -85,11 +85,11 @@
      *            How long before the object expires, in ms, e.g. 1000 = 1
      *            second.
      */
-    public CachedObject(T object, long expires)
+    public CachedObject(final T object, final long expires)
     {
         if (expires == DEFAULT)
         {
-            this.expires = this.defaultAge;
+            this.expires = this.DEFAULT_AGE;
         } else {
             this.expires = expires;
         }
@@ -135,11 +135,11 @@
      * @param expires
      *            Expiration interval in millis ( 1 second = 1000 millis)
      */
-    public void setExpires(long expires)
+    public void setExpires(final long expires)
     {
         if (expires == DEFAULT)
         {
-            this.expires = this.defaultAge;
+            this.expires = this.DEFAULT_AGE;
         }
         else
         {
@@ -161,7 +161,7 @@
      * @param stale
      *            Whether the object is stale or not.
      */
-    public void setStale(boolean stale)
+    public void setStale(final boolean stale)
     {
         this.stale.set( stale );
     }
diff --git a/src/java/org/apache/fulcrum/cache/RefreshableCachedObject.java b/src/java/org/apache/fulcrum/cache/RefreshableCachedObject.java
index 27e388c..a563eb2 100644
--- a/src/java/org/apache/fulcrum/cache/RefreshableCachedObject.java
+++ b/src/java/org/apache/fulcrum/cache/RefreshableCachedObject.java
@@ -46,13 +46,16 @@
     /**
      * How long to wait before removing an untouched object from the cache.
      * Negative numbers mean never remove (the default).
+     * 
+     * time to live in millisec, getter/setter ({@link #getTTL()}
+     * 
      */
-    private transient long timeToLive = -1;
+    private long timeToLive = -1;
 
     /**
      * The last time the Object was accessed from the cache.
      */
-    private transient long lastAccess;
+    private long lastAccess;
 
     /**
      * Constructor; sets the object to expire in the default time (30 minutes).
@@ -60,10 +63,10 @@
      * @param object
      *            The object you want to cache.
      */
-    public RefreshableCachedObject(T object)
+    public RefreshableCachedObject(final T object)
     {
         super(object);
-        this.lastAccess = System.currentTimeMillis();
+        setLastAccess(System.currentTimeMillis());
     }
 
     /**
@@ -75,10 +78,10 @@
      *            How long before the object expires, in ms, e.g. 1000 = 1
      *            second.
      */
-    public RefreshableCachedObject(T object, long expires)
+    public RefreshableCachedObject(final T object, final long expires)
     {
         super(object, expires);
-        this.lastAccess = System.currentTimeMillis();
+        setLastAccess(System.currentTimeMillis());
     }
 
     /**
@@ -87,9 +90,11 @@
      * @param timeToLive
      *            the new Value in milliseconds
      */
-    public synchronized void setTTL(long timeToLive)
+    public void setTTL(final long timeToLive)
     {
-        this.timeToLive = timeToLive;
+        synchronized(this) {
+            this.timeToLive = timeToLive;
+        }
     }
 
     /**
@@ -97,17 +102,21 @@
      *
      * @return The current timeToLive value (in milliseconds)
      */
-    public synchronized long getTTL()
+    public long getTTL()
     {
-        return this.timeToLive;
+        synchronized(this) {
+            return this.timeToLive;
+        }
     }
 
     /**
      * Sets the last access time to the current time.
      */
-    public synchronized void touch()
+    public void touch()
     {
-        this.lastAccess = System.currentTimeMillis();
+        synchronized(this) {
+            this.lastAccess = System.currentTimeMillis();
+        }
     }
 
     /**
@@ -116,14 +125,16 @@
      * 
      * @return boolean status of object
      */
-    public synchronized boolean isUntouched()
+    public boolean isUntouched()
     {
-    	boolean untouched = false;
-        if (this.lastAccess + this.timeToLive < System.currentTimeMillis())
-        {
-        	untouched = true;
+        boolean untouched = false;
+        synchronized(this) {
+            if (this.lastAccess + this.timeToLive < System.currentTimeMillis())
+            {
+            	untouched = true;
+            }
+            return untouched;
         }
-        return untouched;
     }
 
     /**
@@ -138,4 +149,14 @@
             refreshable.refresh();
         }
     }
+
+    public long getLastAccess()
+    {
+        return lastAccess;
+    }
+
+    public void setLastAccess(long lastAccess)
+    {
+        this.lastAccess = lastAccess;
+    }
 }
diff --git a/src/java/org/apache/fulcrum/cache/impl/DefaultGlobalCacheService.java b/src/java/org/apache/fulcrum/cache/impl/DefaultGlobalCacheService.java
index f2d04a4..dff4501 100644
--- a/src/java/org/apache/fulcrum/cache/impl/DefaultGlobalCacheService.java
+++ b/src/java/org/apache/fulcrum/cache/impl/DefaultGlobalCacheService.java
@@ -98,6 +98,11 @@
 
     /** flag to stop the housekeeping thread when the component is disposed. */
     private transient boolean continueThread;
+    
+    public DefaultGlobalCacheService()
+    {
+     
+    }
 
     /**
      * Get the Cache Check Frequency in milliseconds
@@ -171,7 +176,7 @@
      *            The object to cache.
      */
     @Override
-    public <T> void addObject(String objectId, CachedObject<T> object)
+    public <T> void addObject(final String objectId, final CachedObject<T> object)
     {
         // If the cache already contains the key, remove it and add
         // the fresh one.
@@ -336,8 +341,8 @@
     @Override
     public int getCacheSize() throws IOException
     {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        ObjectOutputStream out = new ObjectOutputStream(baos);
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        final ObjectOutputStream out = new ObjectOutputStream(baos);
         out.writeObject(this.cache);
         out.flush();
         //
diff --git a/src/java/org/apache/fulcrum/cache/impl/EHCacheService.java b/src/java/org/apache/fulcrum/cache/impl/EHCacheService.java
index 765c746..6be51bf 100644
--- a/src/java/org/apache/fulcrum/cache/impl/EHCacheService.java
+++ b/src/java/org/apache/fulcrum/cache/impl/EHCacheService.java
@@ -87,6 +87,10 @@
     /** A cache instance */
     private Cache cache;
 
+    public EHCacheService()
+    {
+     
+    }
     // ---------------- Avalon Lifecycle Methods ---------------------
 
     /**
diff --git a/src/java/org/apache/fulcrum/cache/impl/JCSCacheService.java b/src/java/org/apache/fulcrum/cache/impl/JCSCacheService.java
index d7f99f0..3d154e3 100644
--- a/src/java/org/apache/fulcrum/cache/impl/JCSCacheService.java
+++ b/src/java/org/apache/fulcrum/cache/impl/JCSCacheService.java
@@ -90,6 +90,11 @@
 
     /** flag to stop the housekeeping thread when the component is disposed. */
     private boolean continueThread;
+    
+    public JCSCacheService()
+    {
+        
+    }
 
     // ---------------- Avalon Lifecycle Methods ---------------------
 
@@ -150,7 +155,7 @@
      * @see org.apache.fulcrum.cache.GlobalCacheService#getObject(java.lang.String)
      */
     @Override
-	public <T> CachedObject<T> getObject(String objectId) throws ObjectExpiredException
+	public <T> CachedObject<T> getObject(final String objectId) throws ObjectExpiredException
     {
         @SuppressWarnings("unchecked")
         CachedObject<T> cachedObject = (CachedObject<T>)this.cacheManager.getFromGroup(objectId, group);
@@ -213,9 +218,10 @@
             {
                 getLogger()
                         .warn(
-                                "Object with id ["
+                                "Object (contents) with id ["
                                         + objectId
-                                        + "] is not serializable. Expect problems with auxiliary caches.");
+                                        + "] is not serializable. Expect problems with auxiliary caches: " + 
+                                        cachedObject.getContents().getClass().getSimpleName());
             }
 
             ElementAttributes attrib = (ElementAttributes) this.cacheManager.getDefaultElementAttributes();
diff --git a/src/test/TestComponentConfig.xml b/src/test/TestComponentConfig.xml
index 8a262ab..7f48264 100644
--- a/src/test/TestComponentConfig.xml
+++ b/src/test/TestComponentConfig.xml
@@ -18,7 +18,7 @@
  under the License.
 -->
 <componentConfig>
-    <cache cacheInitialSize="20" cacheCheckFrequency="5"/>
+    <cache cacheInitialSize="20" cacheCheckFrequency="5000"/>
     <ehcache>
         <!--  in millisecs -->
         <cacheCheckFrequency>5000</cacheCheckFrequency>
diff --git a/src/test/cache.ccf b/src/test/cache.ccf
index e03c134..a7b0c8e 100644
--- a/src/test/cache.ccf
+++ b/src/test/cache.ccf
@@ -16,6 +16,7 @@
 # under the License.
 # Java Caching System configuration
 
+# to activate disk cache set to jcs.region.default=DC2
 jcs.default=
 jcs.default.cacheattributes=org.apache.commons.jcs3.engine.CompositeCacheAttributes
 jcs.default.cacheattributes.MaxObjects=1000
@@ -27,13 +28,43 @@
 #jcs.default.cacheattributes.MaxSpoolPerRun=500
 jcs.default.elementattributes=org.apache.commons.jcs3.engine.ElementAttributes
 
-# isEternal is assumed by default in Fulcrum Cache 
+# isEternal is assumed by default in Fulcrum Cache Refreshable true else false
 jcs.default.elementattributes.IsEternal=false
 ## memory shrinking end
 
+# not used, only default
 jcs.region.fulcrum=
 jcs.region.fulcrum.cacheattributes=org.apache.commons.jcs3.engine.CompositeCacheAttributes
 jcs.region.fulcrum.cacheattributes.MaxObjects=100
 jcs.region.fulcrum.cacheattributes.MemoryCacheName=org.apache.commons.jcs3.engine.memory.lru.LRUMemoryCache
 jcs.region.fulcrum.elementattributes=org.apache.commons.jcs3.engine.ElementAttributes
 
+##############################################################
+################## AUXILIARY CACHES AVAILABLE ################
+
+# Disk Cache Using a Pooled Event Queue -- this allows you
+# to control the maximum number of threads it will use.
+# Each region uses 1 thread by default in the SINGLE model.
+# adding more threads than regions does not help performance.
+# If you want to use a separate pool for each disk cache, either use
+# the single model or define a different auxiliary for each region and use the Pooled type.
+# SINGLE is generally best unless you have a huge # of regions.
+jcs.auxiliary.DC2=org.apache.commons.jcs3.auxiliary.disk.indexed.IndexedDiskCacheFactory
+jcs.auxiliary.DC2.attributes=org.apache.commons.jcs3.auxiliary.disk.indexed.IndexedDiskCacheAttributes
+jcs.auxiliary.DC2.attributes.DiskPath=target/test-sandbox/raf
+jcs.auxiliary.DC2.attributes.MaxPurgatorySize=10000
+jcs.auxiliary.DC2.attributes.MaxKeySize=10000
+jcs.auxiliary.DC2.attributes.OptimizeAtRemoveCount=300000
+jcs.auxiliary.DC2.attributes.OptimizeOnShutdown=true
+jcs.auxiliary.DC2.attributes.EventQueueType=POOLED
+jcs.auxiliary.DC2.attributes.EventQueuePoolName=disk_cache_event_queue
+
+##############################################################
+################## OPTIONAL THREAD POOL CONFIGURATION ########
+
+# Disk Cache Event Queue Pool
+thread_pool.disk_cache_event_queue.useBoundary=false
+thread_pool.disk_cache_event_queue.maximumPoolSize=15
+thread_pool.disk_cache_event_queue.minimumPoolSize=1
+thread_pool.disk_cache_event_queue.keepAliveTime=3500
+thread_pool.disk_cache_event_queue.startUpSize=1
\ No newline at end of file
diff --git a/src/test/org/apache/fulcrum/cache/CacheTest.java b/src/test/org/apache/fulcrum/cache/CacheTest.java
index 04d849c..6c2ab9b 100644
--- a/src/test/org/apache/fulcrum/cache/CacheTest.java
+++ b/src/test/org/apache/fulcrum/cache/CacheTest.java
@@ -290,6 +290,7 @@
         // Flush Cache
         this.globalCache.flushCache();
         // Wait 15 seconds, 3 Refresh
+        // if using disk cache, you might have to wait longer  
         Thread.sleep((getCacheRefresh() * 2) + 1);
         assertEquals( 0, this.globalCache.getNumberOfObjects(),
                 "After refresh");
@@ -356,6 +357,7 @@
                 getTestExpireTime());
         assertNotNull( cacheObject, "Failed to create a cachable object");
         long addTime = System.currentTimeMillis();
+        log.info( "Adding refreshable object to cache: {}", cacheObject );
         this.globalCache.addObject(cacheKey, cacheObject);
         // Try to get un-expired object
         try
@@ -455,7 +457,8 @@
         assertEquals(getTestExpireTime(), cacheObject
                 .getTTL(),
                 "Returned TimeToLive");
-        // Add object to Cache
+        // Add object to Cache        
+        log.info( "Adding refreshable object to cache: {}", cacheObject );
         this.globalCache.addObject(cacheKey, cacheObject);
         long addTime = System.currentTimeMillis();
         // Try to get un-expired object
@@ -622,7 +625,7 @@
         {
             DefaultGlobalCacheService cache =
                 (DefaultGlobalCacheService)this.lookup(GlobalCacheService.ROLE);
-            return cache.getCacheCheckFrequency() * 1000L;
+            return cache.getCacheCheckFrequency();
         }
         catch (ComponentException e)
         {
@@ -633,7 +636,7 @@
     /**
      * How long until it expires
      *
-     * @return the cache refresh plus 1000.
+     * @return the cache refresh plus 1000 millisec.
      */
     private long getTestExpireTime()
     {
diff --git a/xdocs/index.xml b/xdocs/index.xml
index bd608ba..51e0784 100644
--- a/xdocs/index.xml
+++ b/xdocs/index.xml
@@ -87,8 +87,8 @@
           <td>[0|1]</td>
           <td>
             The cache uses a background thread to check for expired objects.
-            This defines the time between two checks in seconds. The default
-            is 5.
+            This defines the time between two checks in milliseconds. The default
+            is 5000.
           </td>
         </tr>
       </table>
@@ -96,7 +96,7 @@
 
     <subsection name="Component Configuration Example">
       <source><![CDATA[
-    <cache cacheInitialSize="20" cacheCheckFrequency="5"/>
+    <cache cacheInitialSize="20" cacheCheckFrequency="5000"/>
       ]]></source>
     </subsection>
   </section>