This is an automated email from the ASF dual-hosted git repository.

tv pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jcs.git

commit 9f93ba7c4d496a9a28fcb2d01855f363e9b49e3e
Author: Thomas Vandahl <[email protected]>
AuthorDate: Sun Feb 8 17:07:18 2026 +0100

    First steps to make configurations immutable
---
 .../jcs4/engine/CompositeCacheAttributes.java      | 434 ++++++++-------------
 .../engine/behavior/ICompositeCacheAttributes.java |  31 +-
 .../jcs4/engine/control/CompositeCache.java        |  60 +--
 .../engine/control/CompositeCacheConfigurator.java |  32 +-
 .../jcs4/engine/control/CompositeCacheManager.java |  16 +-
 .../AbstractDoubleLinkedListMemoryCache.java       |   4 +-
 .../jcs4/engine/memory/AbstractMemoryCache.java    |   4 +-
 .../jcs4/engine/memory/lru/LHMLRUMemoryCache.java  |   6 +-
 .../engine/memory/shrinking/ShrinkerThread.java    |   4 +-
 .../memory/soft/SoftReferenceMemoryCache.java      |   2 +-
 .../jcs4/utils/config/ConfigurationBuilder.java    | 252 ++++++++++++
 .../commons/jcs4/utils/config/OptionConverter.java |  35 +-
 .../utils/discovery/UDPDiscoveryAttributes.java    |   1 +
 .../commons/jcs4/access/CacheAccessUnitTest.java   |  26 +-
 .../jcs4/access/SystemPropertyUnitTest.java        |   4 +-
 .../disk/jdbc/JDBCDiskCacheSharedPoolUnitTest.java |   1 -
 .../jcs4/engine/ElementAttributesUtils.java        |  18 -
 .../jcs4/engine/SystemPropertyUsageUnitTest.java   |   4 +-
 .../CompositeCacheConfiguratorUnitTest.java        |   2 +-
 .../control/CompositeCacheDiskUsageUnitTest.java   |  49 ++-
 .../engine/control/CompositeCacheManagerTest.java  |   2 +-
 .../engine/control/CompositeCacheUnitTest.java     |  30 +-
 .../engine/control/MockCompositeCacheManager.java  |   2 +-
 .../memory/fifo/FIFOMemoryCacheUnitTest.java       |  16 +-
 .../memory/lru/LHMLRUMemoryCacheUnitTest.java      |  16 +-
 .../engine/memory/mru/MRUMemoryCacheUnitTest.java  |  16 +-
 .../memory/shrinking/ShrinkerThreadUnitTest.java   |  62 +--
 .../soft/SoftReferenceMemoryCacheUnitTest.java     |  12 +-
 .../commons/jcs4/log/LogManagerUnitTest.java       |  33 --
 .../test-conf/TestBlockDiskCacheSteadyLoad.ccf     |   2 +-
 .../src/test/test-conf/TestDiskCacheSteadyLoad.ccf |   2 +-
 .../test/test-conf/TestDiskCacheUsagePattern.ccf   |   4 +-
 .../src/test/test-conf/TestJCS-73.ccf              |   2 +-
 xdocs/RegionProperties.xml                         |   2 +-
 xdocs/UpgradingFrom3x.xml                          |  19 +
 35 files changed, 661 insertions(+), 544 deletions(-)

diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/CompositeCacheAttributes.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/CompositeCacheAttributes.java
index 9cfda3d9..505a9e2e 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/CompositeCacheAttributes.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/CompositeCacheAttributes.java
@@ -28,12 +28,47 @@ import 
org.apache.commons.jcs4.engine.behavior.ICompositeCacheAttributes;
  * If all the default attributes are not defined in the default region 
definition in the cache.ccf,
  * the hard coded defaults will be used.
  */
-public class CompositeCacheAttributes
-    implements ICompositeCacheAttributes
+public record CompositeCacheAttributes(
+        /** The name of this cache region. */
+        String cacheName,
+
+        /** The maximum objects that the memory cache will be allowed to hold. 
*/
+        int maxObjects,
+
+        /** Allow lateral caches */
+        boolean useLateral,
+
+        /** Whether we should use a disk cache if it is configured. */
+        boolean useDisk,
+
+        /** Whether or not we should run the memory shrinker thread. */
+        boolean useMemoryShrinker,
+
+        /** ShrinkerIntervalSeconds */
+        long shrinkerIntervalSeconds,
+
+        /** The maximum number the shrinker will spool to disk per run. */
+        int maxSpoolPerRun,
+
+        /** MaxMemoryIdleTimeSeconds */
+        long maxMemoryIdleTimeSeconds,
+
+        /** The name of the memory cache implementation class. */
+        String memoryCacheName,
+
+        /** Set via DISK_USAGE_PATTERN_NAME */
+        DiskUsagePattern diskUsagePattern,
+
+        /** How many to spool to disk at a time. */
+        int spoolChunkSize
+) implements ICompositeCacheAttributes
 {
     /** Don't change */
     private static final long serialVersionUID = 6754049978134196787L;
 
+    /** Default max objects value */
+    private static final int DEFAULT_MAX_OBJECTS = 100;
+
     /** Default lateral switch */
     private static final boolean DEFAULT_USE_LATERAL = true;
 
@@ -43,339 +78,184 @@ public class CompositeCacheAttributes
     /** Default shrinker setting */
     private static final boolean DEFAULT_USE_SHRINKER = false;
 
-    /** Default max objects value */
-    private static final int DEFAULT_MAX_OBJECTS = 100;
-
-    /** Default */
-    private static final int DEFAULT_MAX_MEMORY_IDLE_TIME_SECONDS = 60 * 120;
-
     /** Default interval to run the shrinker */
     private static final int DEFAULT_SHRINKER_INTERVAL_SECONDS = 30;
 
     /** Default */
     private static final int DEFAULT_MAX_SPOOL_PER_RUN = -1;
 
+    /** Default */
+    private static final int DEFAULT_MAX_MEMORY_IDLE_TIME_SECONDS = 60 * 120;
+
     /** Default */
     private static final String DEFAULT_MEMORY_CACHE_NAME = 
"org.apache.commons.jcs4.engine.memory.lru.LRUMemoryCache";
 
     /** Default number to send to disk at a time when memory fills. */
     private static final int DEFAULT_CHUNK_SIZE = 2;
 
-    /** Allow lateral caches */
-    private boolean useLateral = DEFAULT_USE_LATERAL;
-
-    /** Whether we should use a disk cache if it is configured. */
-    private boolean useDisk = DEFAULT_USE_DISK;
-
-    /** Whether or not we should run the memory shrinker thread. */
-    private boolean useMemoryShrinker = DEFAULT_USE_SHRINKER;
-
-    /** The maximum objects that the memory cache will be allowed to hold. */
-    private int maxObjs = DEFAULT_MAX_OBJECTS;
-
-    /** MaxMemoryIdleTimeSeconds */
-    private long maxMemoryIdleTimeSeconds = 
DEFAULT_MAX_MEMORY_IDLE_TIME_SECONDS;
-
-    /** ShrinkerIntervalSeconds */
-    private long shrinkerIntervalSeconds = DEFAULT_SHRINKER_INTERVAL_SECONDS;
-
-    /** The maximum number the shrinker will spool to disk per run. */
-    private int maxSpoolPerRun = DEFAULT_MAX_SPOOL_PER_RUN;
-
-    /** The name of this cache region. */
-    private String cacheName;
-
-    /** The name of the memory cache implementation class. */
-    private String memoryCacheName;
-
-    /** Set via DISK_USAGE_PATTERN_NAME */
-    private DiskUsagePattern diskUsagePattern = DiskUsagePattern.SWAP;
-
-    /** How many to spool to disk at a time. */
-    private int spoolChunkSize = DEFAULT_CHUNK_SIZE;
-
-    /**
-     * Constructor for the CompositeCacheAttributes object
-     */
-    public CompositeCacheAttributes()
-    {
-        // set this as the default so the configuration is a bit simpler
-        memoryCacheName = DEFAULT_MEMORY_CACHE_NAME;
-    }
-
-    /**
-     * @see Object#clone()
-     */
-    @Override
-    public ICompositeCacheAttributes clone()
-    {
-        try
-        {
-            return (ICompositeCacheAttributes)super.clone();
-        }
-        catch (final CloneNotSupportedException e)
-        {
-            throw new IllegalStateException("Clone not supported. This should 
never happen.", e);
-        }
-    }
-
-    /**
-     * Gets the cacheName attribute of the CompositeCacheAttributes object
-     *
-     * @return The cacheName value
-     */
-    @Override
-    public String getCacheName()
-    {
-        return this.cacheName;
-    }
-
-    /**
-     * @return the diskUsagePattern.
-     */
-    @Override
-    public DiskUsagePattern getDiskUsagePattern()
-    {
-        return diskUsagePattern;
-    }
-
-    /**
-     * If UseMemoryShrinker is true the memory cache should auto-expire 
elements to reclaim space.
-     *
-     * @return The MaxMemoryIdleTimeSeconds value
-     */
-    @Override
-    public long getMaxMemoryIdleTimeSeconds()
-    {
-        return this.maxMemoryIdleTimeSeconds;
-    }
-
-    /**
-     * Gets the maxObjects attribute of the CompositeCacheAttributes object
-     *
-     * @return The maxObjects value
-     */
-    @Override
-    public int getMaxObjects()
-    {
-        return this.maxObjs;
-    }
-
-    /**
-     * If UseMemoryShrinker is true the memory cache should auto-expire 
elements to reclaim space.
-     * This gets the maximum number of items to spool per run.
-     *
-     * @return The maxSpoolPerRun value
-     */
-    @Override
-    public int getMaxSpoolPerRun()
-    {
-        return this.maxSpoolPerRun;
-    }
-
-    /**
-     * Gets the memoryCacheName attribute of the CompositeCacheAttributes 
object
-     *
-     * @return The memoryCacheName value
-     */
-    @Override
-    public String getMemoryCacheName()
-    {
-        return this.memoryCacheName;
-    }
-
-    /**
-     * If UseMemoryShrinker is true the memory cache should auto-expire 
elements to reclaim space.
-     * This gets the shrinker interval.
-     *
-     * @return The ShrinkerIntervalSeconds value
-     */
-    @Override
-    public long getShrinkerIntervalSeconds()
-    {
-        return this.shrinkerIntervalSeconds;
-    }
-
-    /**
-     * Number to send to disk at the time when memory is full.
-     *
-     * @return int
-     */
-    @Override
-    public int getSpoolChunkSize()
-    {
-        return spoolChunkSize;
-    }
-
-    /**
-     * Gets the useDisk attribute of the CompositeCacheAttributes object
-     *
-     * @return The useDisk value
-     */
-    @Override
-    public boolean isUseDisk()
-    {
-        return useDisk;
-    }
-
-    /**
-     * Gets the useLateral attribute of the CompositeCacheAttributes object
-     *
-     * @return The useLateral value
-     */
-    @Override
-    public boolean isUseLateral()
-    {
-        return this.useLateral;
-    }
+    /** Record with all defaults set */
+    private static final CompositeCacheAttributes DEFAULT = new 
CompositeCacheAttributes(
+            null,
+            DEFAULT_MAX_OBJECTS,
+            DEFAULT_USE_LATERAL,
+            DEFAULT_USE_DISK,
+            DEFAULT_USE_SHRINKER,
+            DEFAULT_SHRINKER_INTERVAL_SECONDS,
+            DEFAULT_MAX_SPOOL_PER_RUN,
+            DEFAULT_MAX_MEMORY_IDLE_TIME_SECONDS,
+            DEFAULT_MEMORY_CACHE_NAME,
+            DiskUsagePattern.SWAP,
+            DEFAULT_CHUNK_SIZE
+          );
 
     /**
-     * Tests whether the memory cache should perform background memory 
shrinkage.
-     *
-     * @return The UseMemoryShrinker value
+     * @return an object containing the default settings
      */
-    @Override
-    public boolean isUseMemoryShrinker()
+    public static CompositeCacheAttributes defaults()
     {
-        return this.useMemoryShrinker;
+        return DEFAULT;
     }
 
     /**
-     * Sets the cacheName attribute of the CompositeCacheAttributes object
+     * Sets the name of the cache, referenced by the appropriate manager.
      *
-     * @param s The new cacheName value
+     * @param s
+     *            The new cacheName value
      */
     @Override
-    public void setCacheName( final String s )
-    {
-        this.cacheName = s;
-    }
-
-    /**
-     * By default this is SWAP_ONLY.
-     *
-     * @param diskUsagePattern The diskUsagePattern to set.
-     */
-    public void setDiskUsagePattern( final DiskUsagePattern diskUsagePattern )
-    {
-        this.diskUsagePattern = diskUsagePattern;
-    }
-
-    /**
-     * Translates the name to the disk usage pattern short value.
-     * <p>
-     * The allowed values are SWAP and UPDATE.
-     *
-     * @param diskUsagePatternName The diskUsagePattern to set.
-     */
-    public void setDiskUsagePatternName( final String diskUsagePatternName )
-    {
-        if ( diskUsagePatternName != null )
-        {
-            final String name = diskUsagePatternName.toUpperCase().trim();
-            if ( name.startsWith( "SWAP" ) )
-            {
-                setDiskUsagePattern( DiskUsagePattern.SWAP );
-            }
-            else if ( name.startsWith( "UPDATE" ) )
-            {
-                setDiskUsagePattern( DiskUsagePattern.UPDATE );
-            }
-        }
-    }
-
-    /**
-     * If UseMemoryShrinker is true the memory cache should auto-expire 
elements to reclaim space.
-     *
-     * @param seconds The new MaxMemoryIdleTimeSeconds value
-     */
-    public void setMaxMemoryIdleTimeSeconds( final long seconds )
-    {
-        this.maxMemoryIdleTimeSeconds = seconds;
-    }
-
-    /**
-     * Sets the maxObjects attribute of the CompositeCacheAttributes object
-     *
-     * @param maxObjs The new maxObjects value
-     */
-    public void setMaxObjects( final int maxObjs )
-    {
-        this.maxObjs = maxObjs;
-    }
-
-    /**
-     * If UseMemoryShrinker is true the memory cache should auto-expire 
elements to reclaim space.
-     * This sets the maximum number of items to spool per run.
-     * <p>
-     * If the value is -1, then there is no limit to the number of items to be 
spooled.
-     *
-     * @param maxSpoolPerRun The new maxSpoolPerRun value
-     */
-    public void setMaxSpoolPerRun( final int maxSpoolPerRun )
+    public CompositeCacheAttributes withCacheName(String s)
     {
-        this.maxSpoolPerRun = maxSpoolPerRun;
+        return new CompositeCacheAttributes(s,
+                maxObjects(),
+                useLateral(),
+                useDisk(),
+                useMemoryShrinker(),
+                shrinkerIntervalSeconds(),
+                maxSpoolPerRun(),
+                maxMemoryIdleTimeSeconds(),
+                memoryCacheName(),
+                diskUsagePattern(),
+                spoolChunkSize());
     }
 
     /**
-     * Sets the memoryCacheName attribute of the CompositeCacheAttributes 
object
+     * Sets the size of the cache.
      *
-     * @param s The new memoryCacheName value
+     * @param maxObjects the new maxObjects value
      */
-    public void setMemoryCacheName( final String s )
+    public CompositeCacheAttributes withMaxObjects(int maxObjects)
     {
-        this.memoryCacheName = s;
+        return new CompositeCacheAttributes(cacheName(),
+                maxObjects,
+                useLateral(),
+                useDisk(),
+                useMemoryShrinker(),
+                shrinkerIntervalSeconds(),
+                maxSpoolPerRun(),
+                maxMemoryIdleTimeSeconds(),
+                memoryCacheName(),
+                diskUsagePattern(),
+                spoolChunkSize());
     }
 
     /**
-     * If UseMemoryShrinker is true the memory cache should auto-expire 
elements to reclaim space.
-     * This sets the shrinker interval.
+     * Sets the maximum number of elements to spool per shrinker run.
      *
-     * @param seconds The new ShrinkerIntervalSeconds value
+     * @param maxSpoolPerRun the new maxSpoolPerRun value
      */
-    public void setShrinkerIntervalSeconds( final long seconds )
+    public CompositeCacheAttributes withMaxSpoolPerRun(int maxSpoolPerRun)
     {
-        this.shrinkerIntervalSeconds = seconds;
+        return new CompositeCacheAttributes(cacheName(),
+                maxObjects(),
+                useLateral(),
+                useDisk(),
+                useMemoryShrinker(),
+                shrinkerIntervalSeconds(),
+                maxSpoolPerRun,
+                maxMemoryIdleTimeSeconds(),
+                memoryCacheName(),
+                diskUsagePattern(),
+                spoolChunkSize());
     }
 
     /**
-     * Number to send to disk at a time.
+     * Sets the maximum memory idle-time in seconds of the cache.
      *
-     * @param spoolChunkSize
+     * @param maxMemoryIdleTimeSeconds the new maxMemoryIdleTimeSeconds value
      */
-    public void setSpoolChunkSize( final int spoolChunkSize )
+    public CompositeCacheAttributes withMaxMemoryIdleTimeSeconds(long 
maxMemoryIdleTimeSeconds)
     {
-        this.spoolChunkSize = spoolChunkSize;
+        return new CompositeCacheAttributes(cacheName(),
+                maxObjects(),
+                useLateral(),
+                useDisk(),
+                useMemoryShrinker(),
+                shrinkerIntervalSeconds(),
+                maxSpoolPerRun(),
+                maxMemoryIdleTimeSeconds,
+                memoryCacheName(),
+                diskUsagePattern(),
+                spoolChunkSize());
     }
 
     /**
-     * Sets the useDisk attribute of the CompositeCacheAttributes object
+     * Sets the memory cache name of the cache.
      *
-     * @param useDisk The new useDisk value
+     * @param memoryCacheName the new memoryCacheName value
      */
-    public void setUseDisk( final boolean useDisk )
+    public CompositeCacheAttributes withMemoryCacheName(String memoryCacheName)
     {
-        this.useDisk = useDisk;
+        return new CompositeCacheAttributes(cacheName(),
+                maxObjects(),
+                useLateral(),
+                useDisk(),
+                useMemoryShrinker(),
+                shrinkerIntervalSeconds(),
+                maxSpoolPerRun(),
+                maxMemoryIdleTimeSeconds(),
+                memoryCacheName,
+                diskUsagePattern(),
+                spoolChunkSize());
     }
 
     /**
-     * Sets the useLateral attribute of the CompositeCacheAttributes object
+     * Sets the disk usage pattern of the cache.
      *
-     * @param b The new useLateral value
+     * @param diskUsagePattern the new diskUsagePattern value
      */
-    public void setUseLateral( final boolean b )
+    public CompositeCacheAttributes withDiskUsagePattern(DiskUsagePattern 
diskUsagePattern)
     {
-        this.useLateral = b;
+        return new CompositeCacheAttributes(cacheName(),
+                maxObjects(),
+                useLateral(),
+                useDisk(),
+                useMemoryShrinker(),
+                shrinkerIntervalSeconds(),
+                maxSpoolPerRun(),
+                maxMemoryIdleTimeSeconds(),
+                memoryCacheName(),
+                diskUsagePattern,
+                spoolChunkSize());
     }
 
     /**
-     * Sets whether the memory cache should perform background memory 
shrinkage.
+     * Sets the spool chunk size of the cache.
      *
-     * @param useShrinker The new UseMemoryShrinker value
+     * @param spoolChunkSize the new spoolChunkSize value
      */
-    public void setUseMemoryShrinker( final boolean useShrinker )
+    public CompositeCacheAttributes withSpoolChunkSize(int spoolChunkSize)
     {
-        this.useMemoryShrinker = useShrinker;
+        return new CompositeCacheAttributes(cacheName(),
+                maxObjects(),
+                useLateral(),
+                useDisk(),
+                useMemoryShrinker(),
+                shrinkerIntervalSeconds(),
+                maxSpoolPerRun(),
+                maxMemoryIdleTimeSeconds(),
+                memoryCacheName(),
+                diskUsagePattern(),
+                spoolChunkSize);
     }
 
     /**
@@ -391,7 +271,7 @@ public class CompositeCacheAttributes
         dump.append( "[ " );
         dump.append( "useLateral = " ).append( useLateral );
         dump.append( ", useDisk = " ).append( useDisk );
-        dump.append( ", maxObjs = " ).append( maxObjs );
+        dump.append( ", maxObjs = " ).append( maxObjects );
         dump.append( ", maxSpoolPerRun = " ).append( maxSpoolPerRun );
         dump.append( ", diskUsagePattern = " ).append( diskUsagePattern );
         dump.append( ", spoolChunkSize = " ).append( spoolChunkSize );
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/behavior/ICompositeCacheAttributes.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/behavior/ICompositeCacheAttributes.java
index 5ec4ade5..ea955d4e 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/behavior/ICompositeCacheAttributes.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/behavior/ICompositeCacheAttributes.java
@@ -25,7 +25,7 @@ import java.io.Serializable;
  * This defines the minimal behavior for the Cache Configuration settings.
  */
 public interface ICompositeCacheAttributes
-    extends Serializable, Cloneable
+    extends Serializable
 {
     enum DiskUsagePattern
     {
@@ -39,22 +39,17 @@ public interface ICompositeCacheAttributes
         UPDATE
     }
 
-    /**
-     * Clone object
-     */
-    ICompositeCacheAttributes clone();
-
     /**
      * Gets the cacheName attribute of the ICompositeCacheAttributes object
      *
      * @return The cacheName value
      */
-    String getCacheName();
+    String cacheName();
 
     /**
      * @return the diskUsagePattern.
      */
-    DiskUsagePattern getDiskUsagePattern();
+    DiskUsagePattern diskUsagePattern();
 
     /**
      * If UseMemoryShrinker is true the memory cache should auto-expire 
elements
@@ -62,14 +57,14 @@ public interface ICompositeCacheAttributes
      *
      * @return The MaxMemoryIdleTimeSeconds value
      */
-    long getMaxMemoryIdleTimeSeconds();
+    long maxMemoryIdleTimeSeconds();
 
     /**
      * Gets the maxObjects attribute of the ICompositeCacheAttributes object
      *
      * @return The maxObjects value
      */
-    int getMaxObjects();
+    int maxObjects();
 
     /**
      * If UseMemoryShrinker is true the memory cache should auto-expire 
elements
@@ -77,7 +72,7 @@ public interface ICompositeCacheAttributes
      *
      * @return The maxSpoolPerRun value
      */
-    int getMaxSpoolPerRun();
+    int maxSpoolPerRun();
 
     /**
      * Gets the memoryCacheName attribute of the ICompositeCacheAttributes
@@ -85,7 +80,7 @@ public interface ICompositeCacheAttributes
      *
      * @return The memoryCacheName value
      */
-    String getMemoryCacheName();
+    String memoryCacheName();
 
     /**
      * If UseMemoryShrinker is true the memory cache should auto-expire 
elements
@@ -93,35 +88,35 @@ public interface ICompositeCacheAttributes
      *
      * @return The ShrinkerIntervalSeconds value
      */
-    long getShrinkerIntervalSeconds();
+    long shrinkerIntervalSeconds();
 
     /**
      * Number to send to disk at time when memory is full.
      *
      * @return int
      */
-    int getSpoolChunkSize();
+    int spoolChunkSize();
 
     /**
      * Gets the useDisk attribute of the ICompositeCacheAttributes object
      *
      * @return The useDisk value
      */
-    boolean isUseDisk();
+    boolean useDisk();
 
     /**
      * Gets the useLateral attribute of the ICompositeCacheAttributes object
      *
      * @return The useLateral value
      */
-    boolean isUseLateral();
+    boolean useLateral();
 
     /**
      * Tests whether the memory cache should perform background memory 
shrinkage.
      *
      * @return The UseMemoryShrinker value
      */
-    boolean isUseMemoryShrinker();
+    boolean useMemoryShrinker();
 
     /**
      * Sets the name of the cache, referenced by the appropriate manager.
@@ -129,5 +124,5 @@ public interface ICompositeCacheAttributes
      * @param s
      *            The new cacheName value
      */
-    void setCacheName( String s );
+    ICompositeCacheAttributes withCacheName( String s );
 }
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/control/CompositeCache.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/control/CompositeCache.java
index f0215018..78378940 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/control/CompositeCache.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/control/CompositeCache.java
@@ -46,9 +46,9 @@ import org.apache.commons.jcs4.engine.CacheStatus;
 import org.apache.commons.jcs4.engine.behavior.ICache;
 import org.apache.commons.jcs4.engine.behavior.ICacheElement;
 import org.apache.commons.jcs4.engine.behavior.ICompositeCacheAttributes;
+import 
org.apache.commons.jcs4.engine.behavior.ICompositeCacheAttributes.DiskUsagePattern;
 import org.apache.commons.jcs4.engine.behavior.IElementAttributes;
 import org.apache.commons.jcs4.engine.behavior.IRequireScheduler;
-import 
org.apache.commons.jcs4.engine.behavior.ICompositeCacheAttributes.DiskUsagePattern;
 import org.apache.commons.jcs4.engine.control.event.ElementEvent;
 import org.apache.commons.jcs4.engine.control.event.behavior.ElementEventType;
 import org.apache.commons.jcs4.engine.control.event.behavior.IElementEvent;
@@ -149,7 +149,7 @@ public class CompositeCache<K, V>
         createMemoryCache(cattr);
 
         log.info("Constructed cache with name [{0}] and cache attributes {1}",
-                cacheAttr.getCacheName(), cattr);
+                cacheAttr.cacheName(), cattr);
     }
 
     /**
@@ -162,7 +162,7 @@ public class CompositeCache<K, V>
     private void copyAuxiliaryRetrievedItemToMemory(final ICacheElement<K, V> 
element)
         throws IOException
     {
-        if (memCache.getCacheAttributes().getMaxObjects() > 0)
+        if (memCache.getCacheAttributes().maxObjects() > 0)
         {
             memCache.update(element);
         }
@@ -185,7 +185,7 @@ public class CompositeCache<K, V>
         {
             try
             {
-                final Class<?> c = Class.forName(cattr.getMemoryCacheName());
+                final Class<?> c = Class.forName(cattr.memoryCacheName());
                 @SuppressWarnings("unchecked") // Need cast
                 final
                 IMemoryCache<K, V> newInstance =
@@ -232,7 +232,7 @@ public class CompositeCache<K, V>
         }
 
         log.info("In DISPOSE, [{0}] fromRemote [{1}]",
-                this.cacheAttr::getCacheName, () -> fromRemote);
+                this.cacheAttr::cacheName, () -> fromRemote);
 
         // Remove us from the cache managers list
         // This will call us back but exit immediately
@@ -268,14 +268,14 @@ public class CompositeCache<K, V>
                     || fromRemote && aux.getCacheType() == 
CacheType.REMOTE_CACHE)
                 {
                     log.info("In DISPOSE, [{0}] SKIPPING auxiliary [{1}] 
fromRemote [{2}]",
-                            this.cacheAttr::getCacheName,
+                            this.cacheAttr::cacheName,
                             () -> aux == null ? "null" : aux.getCacheName(),
                             () -> fromRemote);
                     continue;
                 }
 
                 log.info("In DISPOSE, [{0}] auxiliary [{1}]",
-                        this.cacheAttr::getCacheName, aux::getCacheName);
+                        this.cacheAttr::cacheName, aux::getCacheName);
 
                 // IT USED TO BE THE CASE THAT (If the auxiliary is not a 
lateral, or the cache
                 // attributes
@@ -289,7 +289,7 @@ public class CompositeCache<K, V>
                     memCache.freeElements(numToFree);
 
                     log.info("In DISPOSE, [{0}] put {1} into auxiliary [{2}]",
-                            this.cacheAttr::getCacheName, () -> numToFree,
+                            this.cacheAttr::cacheName, () -> numToFree,
                             aux::getCacheName);
                 }
 
@@ -303,7 +303,7 @@ public class CompositeCache<K, V>
         }
 
         log.info("In DISPOSE, [{0}] disposing of memory cache.",
-                this.cacheAttr::getCacheName);
+                this.cacheAttr::cacheName);
         try
         {
             memCache.dispose();
@@ -363,14 +363,14 @@ public class CompositeCache<K, V>
                 if (isExpired(element))
                 {
                     log.debug("{0} - Memory cache hit, but element expired",
-                            () -> cacheAttr.getCacheName());
+                            this.cacheAttr::cacheName);
 
                     doExpires(element);
                     element = null;
                 }
                 else
                 {
-                    log.debug("{0} - Memory cache hit", () -> 
cacheAttr.getCacheName());
+                    log.debug("{0} - Memory cache hit", 
this.cacheAttr::cacheName);
 
                     // Update counters
                     hitCountRam.incrementAndGet();
@@ -409,7 +409,7 @@ public class CompositeCache<K, V>
                         if (isExpired(element))
                         {
                             log.debug("{0} - Aux cache[{1}] hit, but element 
expired.",
-                                    () -> cacheAttr.getCacheName(), 
aux::getCacheName);
+                                    this.cacheAttr::cacheName, 
aux::getCacheName);
 
                             // This will tell the remotes to remove the item
                             // based on the element's expiration policy. The 
elements attributes
@@ -421,7 +421,7 @@ public class CompositeCache<K, V>
                         else
                         {
                             log.debug("{0} - Aux cache[{1}] hit.",
-                                    () -> cacheAttr.getCacheName(), 
aux::getCacheName);
+                                    this.cacheAttr::cacheName, 
aux::getCacheName);
 
                             // Update counters
                             hitCountAux.incrementAndGet();
@@ -444,7 +444,7 @@ public class CompositeCache<K, V>
         {
             missCountNotFound.incrementAndGet();
 
-            log.debug("{0} - Miss", () -> cacheAttr.getCacheName());
+            log.debug("{0} - Miss", this.cacheAttr::cacheName);
         }
 
         if (element != null)
@@ -484,7 +484,7 @@ public class CompositeCache<K, V>
     @Override
     public String getCacheName()
     {
-        return cacheAttr.getCacheName();
+        return cacheAttr.cacheName();
     }
 
     /**
@@ -795,7 +795,7 @@ public class CompositeCache<K, V>
         {
             missCountNotFound.addAndGet(keys.size() - elements.size());
 
-            log.debug("{0} - {1} Misses", () -> cacheAttr.getCacheName(),
+            log.debug("{0} - {1} Misses", this.cacheAttr::cacheName,
                     () -> keys.size() - elements.size());
         }
 
@@ -869,12 +869,12 @@ public class CompositeCache<K, V>
             if (isExpired(element))
             {
                 log.debug("{0} - Memory cache hit, but element expired",
-                        () -> cacheAttr.getCacheName());
+                        () -> cacheAttr.cacheName());
 
                 doExpires(element);
                 return true;
             }
-            log.debug("{0} - Memory cache hit", () -> 
cacheAttr.getCacheName());
+            log.debug("{0} - Memory cache hit", () -> cacheAttr.cacheName());
 
             // Update counters
             hitCountRam.incrementAndGet();
@@ -1149,7 +1149,7 @@ public class CompositeCache<K, V>
                 if (isExpired(element))
                 {
                     log.debug("{0} - Aux cache[{1}] hit, but element expired.",
-                            () -> cacheAttr.getCacheName(), aux::getCacheName);
+                            () -> cacheAttr.cacheName(), aux::getCacheName);
 
                     // This will tell the remote caches to remove the item
                     // based on the element's expiration policy. The elements 
attributes
@@ -1159,7 +1159,7 @@ public class CompositeCache<K, V>
                     return true;
                 }
                 log.debug("{0} - Aux cache[{1}] hit.",
-                        () -> cacheAttr.getCacheName(), aux::getCacheName);
+                        () -> cacheAttr.cacheName(), aux::getCacheName);
 
                 // Update counters
                 hitCountAux.incrementAndGet();
@@ -1170,7 +1170,7 @@ public class CompositeCache<K, V>
                 catch (final IOException e)
                 {
                     log.error("{0} failed to copy element to memory {1}",
-                            cacheAttr.getCacheName(), element, e);
+                            cacheAttr.cacheName(), element, e);
                 }
             }
 
@@ -1357,7 +1357,7 @@ public class CompositeCache<K, V>
                     });
             });
 
-        log.debug("Called save for [{0}]", cacheAttr::getCacheName);
+        log.debug("Called save for [{0}]", cacheAttr::cacheName);
     }
 
     /**
@@ -1436,10 +1436,10 @@ public class CompositeCache<K, V>
     @Override
     public void setScheduledExecutorService(final ScheduledExecutorService 
scheduledExecutor)
     {
-        if (cacheAttr.isUseMemoryShrinker())
+        if (cacheAttr.useMemoryShrinker())
         {
             future = scheduledExecutor.scheduleAtFixedRate(
-                    new ShrinkerThread<>(this), 0, 
cacheAttr.getShrinkerIntervalSeconds(),
+                    new ShrinkerThread<>(this), 0, 
cacheAttr.shrinkerIntervalSeconds(),
                     TimeUnit.SECONDS);
         }
 
@@ -1477,7 +1477,7 @@ public class CompositeCache<K, V>
             {
                 diskAvailable = true;
 
-                if (cacheAttr.getDiskUsagePattern() == DiskUsagePattern.SWAP)
+                if (cacheAttr.diskUsagePattern() == DiskUsagePattern.SWAP)
                 {
                     // write the last items to disk.2
                     try
@@ -1636,8 +1636,8 @@ public class CompositeCache<K, V>
                 case LATERAL_CACHE:
                     // lateral can't do the checking since it is dependent on 
the
                     // cache region restrictions
-                    log.debug("lateralcache in aux list: cattr {0}", 
cacheAttr::isUseLateral);
-                    if (cacheAttr.isUseLateral() && 
cacheElement.getElementAttributes().getIsLateral() && !localOnly)
+                    log.debug("lateralcache in aux list: cattr {0}", 
cacheAttr::useLateral);
+                    if (cacheAttr.useLateral() && 
cacheElement.getElementAttributes().getIsLateral() && !localOnly)
                     {
                         // DISTRIBUTE LATERALLY
                         // Currently always multicast even if the value is
@@ -1649,9 +1649,9 @@ public class CompositeCache<K, V>
 
                 // update disk if the usage pattern permits
                 case DISK_CACHE:
-                    log.debug("diskcache in aux list: cattr {0}", 
cacheAttr::isUseDisk);
-                    if (cacheAttr.isUseDisk()
-                        && cacheAttr.getDiskUsagePattern() == 
DiskUsagePattern.UPDATE
+                    log.debug("diskcache in aux list: cattr {0}", 
cacheAttr::useDisk);
+                    if (cacheAttr.useDisk()
+                        && cacheAttr.diskUsagePattern() == 
DiskUsagePattern.UPDATE
                         && cacheElement.getElementAttributes().getIsSpool())
                     {
                         aux.update(cacheElement);
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/control/CompositeCacheConfigurator.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/control/CompositeCacheConfigurator.java
index f066dce6..53dfe111 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/control/CompositeCacheConfigurator.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/control/CompositeCacheConfigurator.java
@@ -27,6 +27,7 @@ import org.apache.commons.jcs4.auxiliary.AuxiliaryCache;
 import org.apache.commons.jcs4.auxiliary.AuxiliaryCacheAttributes;
 import org.apache.commons.jcs4.auxiliary.AuxiliaryCacheConfigurator;
 import org.apache.commons.jcs4.auxiliary.AuxiliaryCacheFactory;
+import org.apache.commons.jcs4.engine.CompositeCacheAttributes;
 import org.apache.commons.jcs4.engine.behavior.ICache;
 import org.apache.commons.jcs4.engine.behavior.ICompositeCacheAttributes;
 import org.apache.commons.jcs4.engine.behavior.IElementAttributes;
@@ -36,6 +37,7 @@ import 
org.apache.commons.jcs4.engine.logging.behavior.ICacheEventLogger;
 import org.apache.commons.jcs4.engine.match.KeyMatcherPatternImpl;
 import org.apache.commons.jcs4.engine.match.behavior.IKeyMatcher;
 import org.apache.commons.jcs4.log.Log;
+import org.apache.commons.jcs4.utils.config.ConfigurationBuilder;
 import org.apache.commons.jcs4.utils.config.OptionConverter;
 import org.apache.commons.jcs4.utils.config.PropertySetter;
 
@@ -244,28 +246,24 @@ public class CompositeCacheConfigurator
     protected ICompositeCacheAttributes parseCompositeCacheAttributes( final 
Properties props,
             final String regName, final ICompositeCacheAttributes 
defaultCCAttr, final String regionPrefix )
     {
-        ICompositeCacheAttributes ccAttr;
-
-        final String attrName = regionPrefix + regName + 
CACHE_ATTRIBUTE_PREFIX;
-
-        // auxFactory was not previously initialized.
-        // String prefix = regionPrefix + regName + ATTRIBUTE_PREFIX;
-        ccAttr = OptionConverter.instantiateByKey( props, attrName, null );
-
-        if ( ccAttr == null )
+        final String prefix = regionPrefix + regName + CACHE_ATTRIBUTE_PREFIX;
+        Class<? extends ICompositeCacheAttributes> attributeClass = 
OptionConverter.findClassByKey(props, prefix);
+        if (attributeClass == null)
         {
-            log.info( "No special CompositeCacheAttributes class defined for "
-                    + "key [{0}], using default class.", attrName );
-
-            ccAttr = defaultCCAttr;
+            log.debug("Using default composite cache attributes class for 
region \"{0}\"", regName);
+            attributeClass = CompositeCacheAttributes.class;
         }
 
-        log.debug( "Parsing options for \"{0}\"", attrName );
+        log.debug("Parsing options for \"{0}\"", prefix);
 
-        PropertySetter.setProperties( ccAttr, props, attrName + "." );
-        ccAttr.setCacheName( regName );
+        ICompositeCacheAttributes ccAttr = 
ConfigurationBuilder.create(attributeClass,
+                // FIXME: This is probably a bug, but SystemPropertyUnitTest 
relies on it.
+                /* defaultCCAttr */ CompositeCacheAttributes.defaults())
+                .fromProperties(props, prefix)
+                .build()
+                .withCacheName( regName );
 
-        log.debug( "End of parsing for \"{0}\"", attrName );
+        log.debug("End of parsing for \"{0}\"", prefix);
         return ccAttr;
     }
 
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/control/CompositeCacheManager.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/control/CompositeCacheManager.java
index 567cfe07..7587d767 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/control/CompositeCacheManager.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/control/CompositeCacheManager.java
@@ -47,12 +47,12 @@ import 
org.apache.commons.jcs4.auxiliary.remote.behavior.IRemoteCacheConstants;
 import org.apache.commons.jcs4.engine.CompositeCacheAttributes;
 import org.apache.commons.jcs4.engine.ElementAttributes;
 import org.apache.commons.jcs4.engine.behavior.ICache;
+import org.apache.commons.jcs4.engine.behavior.ICacheType.CacheType;
 import org.apache.commons.jcs4.engine.behavior.ICompositeCacheAttributes;
 import org.apache.commons.jcs4.engine.behavior.ICompositeCacheManager;
 import org.apache.commons.jcs4.engine.behavior.IElementAttributes;
 import org.apache.commons.jcs4.engine.behavior.IProvideScheduler;
 import org.apache.commons.jcs4.engine.behavior.IShutdownObserver;
-import org.apache.commons.jcs4.engine.behavior.ICacheType.CacheType;
 import org.apache.commons.jcs4.engine.control.event.ElementEventQueue;
 import 
org.apache.commons.jcs4.engine.control.event.behavior.IElementEventQueue;
 import org.apache.commons.jcs4.engine.stats.CacheStats;
@@ -181,7 +181,7 @@ public class CompositeCacheManager
     private final AtomicInteger clients = new AtomicInteger();
 
     /** Default cache attributes for this cache manager */
-    private ICompositeCacheAttributes defaultCacheAttr = new 
CompositeCacheAttributes();
+    private ICompositeCacheAttributes defaultCacheAttr = 
CompositeCacheAttributes.defaults();
 
     /** Default element attributes for this cache manager */
     private IElementAttributes defaultElementAttr = new ElementAttributes();
@@ -405,7 +405,7 @@ public class CompositeCacheManager
 
         // set default cache attr
         this.defaultCacheAttr = configurator.parseCompositeCacheAttributes( 
properties, "",
-                new CompositeCacheAttributes(), DEFAULT_REGION );
+                CompositeCacheAttributes.defaults(), DEFAULT_REGION );
 
         log.info( "setting defaultCompositeCacheAttributes to {0}", 
this.defaultCacheAttr );
 
@@ -522,7 +522,7 @@ public class CompositeCacheManager
     {
         log.debug( "attr = {0}", attr );
 
-        return (CompositeCache<K, V>) 
caches.computeIfAbsent(cattr.getCacheName(),
+        return (CompositeCache<K, V>) caches.computeIfAbsent(cattr.cacheName(),
                 cacheName -> {
             final CompositeCacheConfigurator configurator = newConfigurator();
             return configurator.parseRegion( getConfigurationProperties(), 
this, cacheName,
@@ -551,8 +551,7 @@ public class CompositeCacheManager
      */
     public <K, V> CompositeCache<K, V> getCache( final String cacheName, final 
ICompositeCacheAttributes cattr )
     {
-        cattr.setCacheName( cacheName );
-        return getCache( cattr, getDefaultElementAttributes() );
+        return getCache( cattr.withCacheName(cacheName), 
getDefaultElementAttributes() );
     }
 
     /**
@@ -565,8 +564,7 @@ public class CompositeCacheManager
      */
     public <K, V> CompositeCache<K, V>  getCache( final String cacheName, 
final ICompositeCacheAttributes cattr, final IElementAttributes attr )
     {
-        cattr.setCacheName( cacheName );
-        return getCache( cattr, attr );
+        return getCache( cattr.withCacheName(cacheName), attr );
     }
 
     /**
@@ -605,7 +603,7 @@ public class CompositeCacheManager
      */
     public ICompositeCacheAttributes getDefaultCacheAttributes()
     {
-        return this.defaultCacheAttr.clone();
+        return this.defaultCacheAttr;
     }
 
     /**
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/AbstractDoubleLinkedListMemoryCache.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/AbstractDoubleLinkedListMemoryCache.java
index 75fe27dc..8bd3407b 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/AbstractDoubleLinkedListMemoryCache.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/AbstractDoubleLinkedListMemoryCache.java
@@ -280,7 +280,7 @@ public abstract class 
AbstractDoubleLinkedListMemoryCache<K, V> extends Abstract
         final int size = map.size();
         // If the element limit is reached, we need to spool
 
-        if (size <= getCacheAttributes().getMaxObjects())
+        if (size <= getCacheAttributes().maxObjects())
         {
             return;
         }
@@ -292,7 +292,7 @@ public abstract class 
AbstractDoubleLinkedListMemoryCache<K, V> extends Abstract
 
         log.debug("About to spool to disk cache, map size: {0}, max objects: 
{1}, "
                 + "maximum items to spool: {2}", () -> size,
-                getCacheAttributes()::getMaxObjects,
+                getCacheAttributes()::maxObjects,
                 () -> chunkSizeCorrected);
 
         // The spool will put them in a disk event queue, so there is no
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/AbstractMemoryCache.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/AbstractMemoryCache.java
index f3a5bca8..49388d0c 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/AbstractMemoryCache.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/AbstractMemoryCache.java
@@ -178,7 +178,7 @@ public abstract class AbstractMemoryCache<K, V>
      */
     public String getCacheName()
     {
-        final String attributeCacheName = this.cacheAttributes.getCacheName();
+        final String attributeCacheName = this.cacheAttributes.cacheName();
         if(attributeCacheName != null)
         {
             return attributeCacheName;
@@ -317,7 +317,7 @@ public abstract class AbstractMemoryCache<K, V>
         putCnt = new AtomicLong();
 
         this.cacheAttributes = hub.getCacheAttributes();
-        this.chunkSize = cacheAttributes.getSpoolChunkSize();
+        this.chunkSize = cacheAttributes.spoolChunkSize();
         this.cache = hub;
 
         this.map = createMap();
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/lru/LHMLRUMemoryCache.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/lru/LHMLRUMemoryCache.java
index bdeaf7eb..216b4c1c 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/lru/LHMLRUMemoryCache.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/lru/LHMLRUMemoryCache.java
@@ -52,7 +52,7 @@ public class LHMLRUMemoryCache<K, V>
          */
         public LHMSpooler()
         {
-            super( (int) ( getCacheAttributes().getMaxObjects() * .5 ), .75F, 
true );
+            super( (int) ( getCacheAttributes().maxObjects() * .5 ), .75F, 
true );
         }
 
         /**
@@ -67,12 +67,12 @@ public class LHMLRUMemoryCache<K, V>
         {
             final ICacheElement<K, V> element = 
eldest.getValue().getCacheElement();
 
-            if ( size() <= getCacheAttributes().getMaxObjects() )
+            if ( size() <= getCacheAttributes().maxObjects() )
             {
                 return false;
             }
             log.debug( "LHMLRU max size: {0}. Spooling element, key: {1}",
-                    () -> getCacheAttributes().getMaxObjects(), 
element::getKey);
+                    () -> getCacheAttributes().maxObjects(), element::getKey);
 
             waterfal( element );
 
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/shrinking/ShrinkerThread.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/shrinking/ShrinkerThread.java
index 004793b4..43437d42 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/shrinking/ShrinkerThread.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/shrinking/ShrinkerThread.java
@@ -59,7 +59,7 @@ public class ShrinkerThread<K, V>
     {
         this.cache = cache;
 
-        final long maxMemoryIdleTimeSeconds = 
cache.getCacheAttributes().getMaxMemoryIdleTimeSeconds();
+        final long maxMemoryIdleTimeSeconds = 
cache.getCacheAttributes().maxMemoryIdleTimeSeconds();
 
         if ( maxMemoryIdleTimeSeconds < 0 )
         {
@@ -70,7 +70,7 @@ public class ShrinkerThread<K, V>
             this.maxMemoryIdleTime = maxMemoryIdleTimeSeconds * 1000;
         }
 
-        this.maxSpoolPerRun = cache.getCacheAttributes().getMaxSpoolPerRun();
+        this.maxSpoolPerRun = cache.getCacheAttributes().maxSpoolPerRun();
         if ( this.maxSpoolPerRun != -1 )
         {
             this.spoolLimit = true;
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/soft/SoftReferenceMemoryCache.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/soft/SoftReferenceMemoryCache.java
index 50360759..32666225 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/soft/SoftReferenceMemoryCache.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/engine/memory/soft/SoftReferenceMemoryCache.java
@@ -200,7 +200,7 @@ public class SoftReferenceMemoryCache<K, V> extends 
AbstractMemoryCache<K, V>
      */
     private void trimStrongReferences()
     {
-        final int max = getCacheAttributes().getMaxObjects();
+        final int max = getCacheAttributes().maxObjects();
         final int startsize = strongReferences.size();
 
         for (int cursize = startsize; cursize > max; cursize--)
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/config/ConfigurationBuilder.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/config/ConfigurationBuilder.java
new file mode 100644
index 00000000..0b7eb7dc
--- /dev/null
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/config/ConfigurationBuilder.java
@@ -0,0 +1,252 @@
+package org.apache.commons.jcs4.utils.config;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.RecordComponent;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.regex.Pattern;
+
+import org.apache.commons.jcs4.log.Log;
+
+/**
+ * Generic builder for record types annotated with @Configurable.
+ * Automatically parses Properties and creates record instances.
+ */
+public class ConfigurationBuilder<T>
+{
+    private static final Log log = Log.getLog(ConfigurationBuilder.class);
+
+    private final Class<T> recordClass;
+    private final Map<String, Object> values = new HashMap<>();
+
+    private ConfigurationBuilder(Class<T> recordClass, Object defaultRecord)
+    {
+        if (!recordClass.isRecord())
+        {
+            throw new IllegalArgumentException(recordClass.getName() + " is 
not a record");
+        }
+        this.recordClass = recordClass;
+
+        if (defaultRecord != null)
+        {
+            initializeDefaults(defaultRecord);
+        }
+    }
+
+    /**
+     * Create a new builder for the given record class and an optional default 
record.
+     */
+    public static <T> ConfigurationBuilder<T> create(Class<T> recordClass)
+    {
+        return new ConfigurationBuilder<>(recordClass, null);
+    }
+
+    /**
+     * Create a new builder for the given record class and an optional default 
record.
+     */
+    public static <T> ConfigurationBuilder<T> create(Class<T> recordClass, 
Object defaultRecord)
+    {
+        return new ConfigurationBuilder<>(recordClass, defaultRecord);
+    }
+
+    /**
+     * Initialize default values from default record.
+     *
+     * @param defaultRecord a record object containing defaults
+     */
+    private void initializeDefaults(Object defaultRecord)
+    {
+        RecordComponent[] components = recordClass.getRecordComponents();
+        for (RecordComponent component : components)
+        {
+            try
+            {
+                Object value = component.getAccessor().invoke(defaultRecord);
+                values.put(component.getName(), value);
+            }
+            catch (ReflectiveOperationException e)
+            {
+                log.error("Error setting defaults for {0}, field {1}",
+                        recordClass, component.getName(), e);
+            }
+        }
+    }
+
+    /**
+     * Load properties from a Properties object with a given prefix.
+     *
+     * @param props the Properties
+     * @param prefix the Prefix
+     */
+    public ConfigurationBuilder<T> fromProperties(Properties props, String 
prefix)
+    {
+        if (props == null || props.isEmpty())
+        {
+            return this;
+        }
+
+        RecordComponent[] components = recordClass.getRecordComponents();
+
+        for (RecordComponent component : components)
+        {
+            // Capitalize first letter of component name
+            String name = 
Pattern.compile("^.").matcher(component.getName()).replaceFirst(
+                    m -> m.group().toUpperCase(Locale.ENGLISH));
+
+            String fullKey = String.join(".", prefix, name);
+            String value = OptionConverter.findAndSubst(fullKey, props);
+
+            if (value != null)
+            {
+                Object parsed = parseValue(value, component.getType());
+                if (parsed != null)
+                {
+                    values.put(component.getName(), parsed);
+                    log.debug("Loaded property {0}: {1}", fullKey, parsed);
+                }
+            }
+        }
+
+        return this;
+    }
+
+    /**
+     * Build the record instance, throwing if any required properties are 
missing.
+     */
+    public T build()
+    {
+        return createInstance();
+    }
+
+    /**
+     * Create the record instance using the canonical constructor.
+     */
+    private T createInstance()
+    {
+        try
+        {
+            RecordComponent[] components = recordClass.getRecordComponents();
+            Class<?>[] paramTypes = new Class<?>[components.length];
+            Object[] params = new Object[components.length];
+
+            for (int i = 0; i < components.length; i++)
+            {
+                paramTypes[i] = components[i].getType();
+                params[i] = values.getOrDefault(components[i].getName(),
+                        // Use null-safe defaults for primitives
+                        getDefaultForType(components[i].getType()));
+            }
+
+            Constructor<T> constructor = 
recordClass.getDeclaredConstructor(paramTypes);
+            T instance = constructor.newInstance(params);
+            log.debug("Created instance of {0}", recordClass.getSimpleName());
+            return instance;
+
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException(
+                "Failed to create instance of " + recordClass.getName(), e
+            );
+        }
+    }
+
+    /**
+     * Parse a string value to the appropriate type.
+     */
+    private Object parseValue(String value, Class<?> type)
+    {
+        if (value == null || value.trim().isEmpty())
+        {
+            return null;
+        }
+
+        String v = value.trim();
+        if ( String.class.isAssignableFrom( type ) )
+        {
+            return v;
+        }
+        if ( Integer.TYPE.isAssignableFrom( type ) )
+        {
+            return Integer.valueOf( v );
+        }
+        if ( Long.TYPE.isAssignableFrom( type ) )
+        {
+            return Long.valueOf( v );
+        }
+        if ( Boolean.TYPE.isAssignableFrom( type ) )
+        {
+            if (Boolean.parseBoolean(v))
+            {
+                return Boolean.TRUE;
+            }
+            else
+            {
+                return Boolean.FALSE;
+            }
+        }
+        else if( type.isEnum() )
+        {
+            @SuppressWarnings({ "unchecked" })
+            final Enum<?> valueOf = Enum.valueOf(type.asSubclass(Enum.class), 
v);
+            return valueOf;
+        }
+        else if ( File.class.isAssignableFrom( type ) )
+        {
+            return new File( v );
+        }
+
+        log.warn("Unknown type for conversion: {0} and value {1}", type, 
value);
+        return null;
+    }
+
+    /**
+     * Get default value for a primitive type.
+     */
+    private Object getDefaultForType(Class<?> type)
+    {
+        if (type == boolean.class)
+        {
+            return false;
+        }
+        if (type == int.class)
+        {
+            return 0;
+        }
+        if (type == long.class)
+        {
+            return 0L;
+        }
+        if (type == double.class)
+        {
+            return 0.0d;
+        }
+        if (type == float.class)
+        {
+            return 0.0f;
+        }
+        return null;
+    }
+}
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/config/OptionConverter.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/config/OptionConverter.java
index 77b1ce29..768af297 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/config/OptionConverter.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/config/OptionConverter.java
@@ -167,6 +167,40 @@ public class OptionConverter
         }
     }
 
+    /**
+     * Get the class object given a class name.
+     *
+     * @param props the Properties class
+     * @param key the key of the Class name in the Properties object
+     *
+     * @return Class object
+     */
+    public static <T> Class<T> findClassByKey(final Properties props, final 
String key)
+    {
+        final String className = findAndSubst( key, props );
+        if (className != null && !className.isBlank())
+        {
+            try
+            {
+                @SuppressWarnings("unchecked") // CCE caught
+                final Class<T> classObj = (Class<T>) Class.forName( 
className.trim() );
+                return classObj;
+
+            }
+            catch (final ClassCastException e)
+            {
+                log.error( "A \"{0}\" object is not assignable to the "
+                        + "generic variable.", className );
+            }
+            catch (final Exception e)
+            {
+                log.error("Could not instantiate class [{0}]", className, e);
+            }
+        }
+
+        return null;
+    }
+
     /**
      * Instantiate an object given a class name. Check that the {@code 
className} is a subclass
      * of {@code superClass}. If that test fails or the object could not be 
instantiated, then
@@ -176,7 +210,6 @@ public class OptionConverter
      * @param defaultValue The object to return in case of non-fulfillment
      * @return instantiated object
      */
-
     public static <T> T instantiateByClassName( final String className, final 
T defaultValue )
     {
         if ( className != null )
diff --git 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/discovery/UDPDiscoveryAttributes.java
 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/discovery/UDPDiscoveryAttributes.java
index 38085704..dc8c63b6 100644
--- 
a/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/discovery/UDPDiscoveryAttributes.java
+++ 
b/commons-jcs4-core/src/main/java/org/apache/commons/jcs4/utils/discovery/UDPDiscoveryAttributes.java
@@ -57,6 +57,7 @@ public record UDPDiscoveryAttributes(
     /** Default amount of time before we remove services that we haven't heard 
from */
     private static final int DEFAULT_MAX_IDLE_TIME_SEC = 180;
 
+    /** Record with all defaults set */
     private static final UDPDiscoveryAttributes DEFAULT = new 
UDPDiscoveryAttributes(
             null,
             -1,
diff --git 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/access/CacheAccessUnitTest.java
 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/access/CacheAccessUnitTest.java
index 7fc64b88..4ad990e8 100644
--- 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/access/CacheAccessUnitTest.java
+++ 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/access/CacheAccessUnitTest.java
@@ -109,9 +109,9 @@ class CacheAccessUnitTest
         final String keyprefix1 = "MyPrefix1";
         final String keyprefix2 = "MyPrefix2";
         final String memoryCacheClassName = 
"org.apache.commons.jcs4.engine.memory.lru.LRUMemoryCache";
-        final CompositeCacheAttributes cattr = new CompositeCacheAttributes();
-        cattr.setMemoryCacheName( memoryCacheClassName );
-        cattr.setMaxObjects( maxMemorySize );
+        final CompositeCacheAttributes cattr = 
CompositeCacheAttributes.defaults()
+                .withMemoryCacheName( memoryCacheClassName )
+                .withMaxObjects(maxMemorySize);
 
         final long maxLife = 9876;
         final ElementAttributes attr = new ElementAttributes();
@@ -164,9 +164,9 @@ class CacheAccessUnitTest
         final String keyprefix1 = "MyPrefix1";
         final String keyprefix2 = "MyPrefix2";
         final String memoryCacheClassName = 
"org.apache.commons.jcs4.engine.memory.lru.LRUMemoryCache";
-        final CompositeCacheAttributes cattr = new CompositeCacheAttributes();
-        cattr.setMemoryCacheName( memoryCacheClassName );
-        cattr.setMaxObjects( maxMemorySize );
+        final CompositeCacheAttributes cattr = 
CompositeCacheAttributes.defaults()
+                .withMemoryCacheName( memoryCacheClassName )
+                .withMaxObjects(maxMemorySize);
 
         final long maxLife = 9876;
         final ElementAttributes attr = new ElementAttributes();
@@ -309,16 +309,15 @@ class CacheAccessUnitTest
     void testRegionDefinitonWithAttributes()
         throws Exception
     {
-        final CompositeCacheAttributes ca = new CompositeCacheAttributes();
-
         final long maxIdleTime = 8765;
-        ca.setMaxMemoryIdleTimeSeconds( maxIdleTime );
+        final CompositeCacheAttributes ca = CompositeCacheAttributes.defaults()
+                .withMaxMemoryIdleTimeSeconds(maxIdleTime);
 
         final CacheAccess<String, String> access = JCS.getInstance( 
"testRegionDefinitonWithAttributes", ca );
         assertNotNull( access, "We should have an access class" );
 
         final ICompositeCacheAttributes ca2 = access.getCacheAttributes();
-        assertEquals( ca.getMaxMemoryIdleTimeSeconds(), 
ca2.getMaxMemoryIdleTimeSeconds(), "Wrong idle time setting." );
+        assertEquals( ca.maxMemoryIdleTimeSeconds(), 
ca2.maxMemoryIdleTimeSeconds(), "Wrong idle time setting." );
     }
 
     /**
@@ -330,10 +329,9 @@ class CacheAccessUnitTest
     void testRegionDefinitonWithBothAttributes()
         throws Exception
     {
-        final CompositeCacheAttributes ca = new CompositeCacheAttributes();
-
         final long maxIdleTime = 8765;
-        ca.setMaxMemoryIdleTimeSeconds( maxIdleTime );
+        final CompositeCacheAttributes ca = CompositeCacheAttributes.defaults()
+                .withMaxMemoryIdleTimeSeconds(maxIdleTime);
 
         final long maxLife = 9876;
         final ElementAttributes attr = new ElementAttributes();
@@ -343,7 +341,7 @@ class CacheAccessUnitTest
         assertNotNull( access, "We should have an access class" );
 
         final ICompositeCacheAttributes ca2 = access.getCacheAttributes();
-        assertEquals( ca.getMaxMemoryIdleTimeSeconds(), 
ca2.getMaxMemoryIdleTimeSeconds(), "Wrong idle time setting." );
+        assertEquals( ca.maxMemoryIdleTimeSeconds(), 
ca2.maxMemoryIdleTimeSeconds(), "Wrong idle time setting." );
     }
 
     /**
diff --git 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/access/SystemPropertyUnitTest.java
 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/access/SystemPropertyUnitTest.java
index d2ac4986..e7cf5d60 100644
--- 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/access/SystemPropertyUnitTest.java
+++ 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/access/SystemPropertyUnitTest.java
@@ -71,7 +71,7 @@ class SystemPropertyUnitTest
         System.setProperty( "MY_SYSTEM_PROPERTY_MAX_SIZE", String.valueOf( 
maxMemory ) );
 
         final CacheAccess<String, String> cache = JCS.getInstance( "test1" );
-        assertEquals( maxMemory, cache.getCacheAttributes().getMaxObjects(),
+        assertEquals( maxMemory, cache.getCacheAttributes().maxObjects(),
                       "We should have used the system property for the memory 
size" );
     }
 
@@ -91,7 +91,7 @@ class SystemPropertyUnitTest
         mgr.configure( "/TestSystemProperties.ccf" );
 
         final CacheAccess<String, String> cache = JCS.getInstance( "missing" );
-        assertEquals( 100, cache.getCacheAttributes().getMaxObjects(),
+        assertEquals( 100, cache.getCacheAttributes().maxObjects(),
                       "We should have used the default property for the memory 
size" );
     }
 }
diff --git 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/disk/jdbc/JDBCDiskCacheSharedPoolUnitTest.java
 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/disk/jdbc/JDBCDiskCacheSharedPoolUnitTest.java
index ef2db0ba..baaf45dd 100644
--- 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/disk/jdbc/JDBCDiskCacheSharedPoolUnitTest.java
+++ 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/auxiliary/disk/jdbc/JDBCDiskCacheSharedPoolUnitTest.java
@@ -68,7 +68,6 @@ public class JDBCDiskCacheSharedPoolUnitTest
         for ( int i = 0; i < items; i++ )
         {
             final String value = jcs.get( i + ":key" );
-
             assertEquals( region + " data " + i, value, "key = [" + i + ":key] 
value = [" + value + "]" );
         }
 
diff --git 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/ElementAttributesUtils.java
 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/ElementAttributesUtils.java
index 29ec5b3a..f12aeefe 100644
--- 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/ElementAttributesUtils.java
+++ 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/ElementAttributesUtils.java
@@ -1,21 +1,3 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
 package org.apache.commons.jcs4.engine;
 
 /*
diff --git 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/SystemPropertyUsageUnitTest.java
 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/SystemPropertyUsageUnitTest.java
index 7129c90a..f67b1d90 100644
--- 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/SystemPropertyUsageUnitTest.java
+++ 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/SystemPropertyUsageUnitTest.java
@@ -78,7 +78,7 @@ class SystemPropertyUsageUnitTest
 
         manager = CompositeCacheManager.getInstance();
 
-        assertEquals( testValue, jcs.getCacheAttributes().getMaxObjects(), 
"System property value is not reflected." );
+        assertEquals( testValue, jcs.getCacheAttributes().maxObjects(), 
"System property value is not reflected." );
     }
 
     /**
@@ -101,7 +101,7 @@ class SystemPropertyUsageUnitTest
         final CacheAccess<String, String> jcs = JCS.getInstance( 
"someCacheNotInFile" );
 
         assertEquals( Integer.parseInt( props.getProperty( 
JCS_DEFAULT_CACHEATTRIBUTES_MAX_OBJECTS ) ),
-                      jcs.getCacheAttributes().getMaxObjects(),
+                      jcs.getCacheAttributes().maxObjects(),
                       "System property value should not be reflected" );
     }
 }
diff --git 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/CompositeCacheConfiguratorUnitTest.java
 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/CompositeCacheConfiguratorUnitTest.java
index d31de23f..8e459454 100644
--- 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/CompositeCacheConfiguratorUnitTest.java
+++ 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/CompositeCacheConfiguratorUnitTest.java
@@ -90,6 +90,6 @@ class CompositeCacheConfiguratorUnitTest
 
         // VERIFY
         final CompositeCache<String, String> cache = manager.getCache( 
regionName );
-        assertEquals( cache.getCacheAttributes().getSpoolChunkSize(), 
chunkSize, "Wrong chunkSize" );
+        assertEquals( cache.getCacheAttributes().spoolChunkSize(), chunkSize, 
"Wrong chunkSize" );
     }
 }
diff --git 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/CompositeCacheDiskUsageUnitTest.java
 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/CompositeCacheDiskUsageUnitTest.java
index b90ef8bb..40e157eb 100644
--- 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/CompositeCacheDiskUsageUnitTest.java
+++ 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/CompositeCacheDiskUsageUnitTest.java
@@ -119,7 +119,6 @@ class CompositeCacheDiskUsageUnitTest
         @Override
         public String getEventLoggingExtraInfo()
         {
-            // TODO Auto-generated method stub
             return null;
         }
 
@@ -220,8 +219,6 @@ class CompositeCacheDiskUsageUnitTest
         @Override
         public void setCacheEventLogger( final ICacheEventLogger 
cacheEventLogger )
         {
-            // TODO Auto-generated method stub
-
         }
 
         /**
@@ -230,8 +227,6 @@ class CompositeCacheDiskUsageUnitTest
         @Override
         public void setElementSerializer( final IElementSerializer 
elementSerializer )
         {
-            // TODO Auto-generated method stub
-
         }
 
         /**
@@ -267,9 +262,9 @@ class CompositeCacheDiskUsageUnitTest
     void testSpoolAllowed()
     {
         // SETUP
-        final CompositeCacheAttributes cattr = new CompositeCacheAttributes();
-        cattr.setCacheName(CACHE_NAME);
-        cattr.setDiskUsagePattern( 
ICompositeCacheAttributes.DiskUsagePattern.SWAP );
+        final CompositeCacheAttributes cattr = 
CompositeCacheAttributes.defaults()
+                .withCacheName(CACHE_NAME)
+                
.withDiskUsagePattern(ICompositeCacheAttributes.DiskUsagePattern.SWAP);
 
         final IElementAttributes attr = new ElementAttributes();
 
@@ -297,9 +292,9 @@ class CompositeCacheDiskUsageUnitTest
     void testSpoolNotAllowed()
     {
         // SETUP
-        final CompositeCacheAttributes cattr = new CompositeCacheAttributes();
-        cattr.setCacheName(CACHE_NAME);
-        cattr.setDiskUsagePattern( 
ICompositeCacheAttributes.DiskUsagePattern.UPDATE );
+        final CompositeCacheAttributes cattr = 
CompositeCacheAttributes.defaults()
+                .withCacheName(CACHE_NAME)
+                
.withDiskUsagePattern(ICompositeCacheAttributes.DiskUsagePattern.UPDATE);
 
         final IElementAttributes attr = new ElementAttributes();
 
@@ -328,8 +323,8 @@ class CompositeCacheDiskUsageUnitTest
         throws CacheException
     {
         final CacheAccess<String, String> swap = JCS.getInstance( "Swap" );
-        assertEquals( ICompositeCacheAttributes.DiskUsagePattern.SWAP, 
swap.getCacheAttributes()
-            .getDiskUsagePattern() );
+        assertEquals( ICompositeCacheAttributes.DiskUsagePattern.SWAP,
+                swap.getCacheAttributes().diskUsagePattern() );
     }
 
     /**
@@ -345,9 +340,9 @@ class CompositeCacheDiskUsageUnitTest
         throws IOException
     {
         // SETUP
-        final CompositeCacheAttributes cattr = new CompositeCacheAttributes();
-        cattr.setCacheName(CACHE_NAME);
-        cattr.setDiskUsagePattern( 
ICompositeCacheAttributes.DiskUsagePattern.UPDATE );
+        final CompositeCacheAttributes cattr = 
CompositeCacheAttributes.defaults()
+                .withCacheName(CACHE_NAME)
+                
.withDiskUsagePattern(ICompositeCacheAttributes.DiskUsagePattern.UPDATE);
 
         final IElementAttributes attr = new ElementAttributes();
 
@@ -381,9 +376,9 @@ class CompositeCacheDiskUsageUnitTest
         throws IOException
     {
         // SETUP
-        final CompositeCacheAttributes cattr = new CompositeCacheAttributes();
-        cattr.setCacheName(CACHE_NAME);
-        cattr.setDiskUsagePattern( 
ICompositeCacheAttributes.DiskUsagePattern.UPDATE );
+        final CompositeCacheAttributes cattr = 
CompositeCacheAttributes.defaults()
+                .withCacheName(CACHE_NAME)
+                
.withDiskUsagePattern(ICompositeCacheAttributes.DiskUsagePattern.UPDATE);
 
         final IElementAttributes attr = new ElementAttributes();
 
@@ -416,9 +411,9 @@ class CompositeCacheDiskUsageUnitTest
         throws IOException
     {
         // SETUP
-        final CompositeCacheAttributes cattr = new CompositeCacheAttributes();
-        cattr.setCacheName(CACHE_NAME);
-        cattr.setDiskUsagePattern( 
ICompositeCacheAttributes.DiskUsagePattern.UPDATE );
+        final CompositeCacheAttributes cattr = 
CompositeCacheAttributes.defaults()
+                .withCacheName(CACHE_NAME)
+                
.withDiskUsagePattern(ICompositeCacheAttributes.DiskUsagePattern.UPDATE);
 
         final IElementAttributes attr = new ElementAttributes();
 
@@ -454,8 +449,8 @@ class CompositeCacheDiskUsageUnitTest
         throws CacheException
     {
         final CacheAccess<String, String> swap = JCS.getInstance( "Update" );
-        assertEquals( ICompositeCacheAttributes.DiskUsagePattern.UPDATE, 
swap.getCacheAttributes()
-            .getDiskUsagePattern() );
+        assertEquals( ICompositeCacheAttributes.DiskUsagePattern.UPDATE,
+                swap.getCacheAttributes().diskUsagePattern() );
     }
 
     /**
@@ -472,9 +467,9 @@ class CompositeCacheDiskUsageUnitTest
         throws IOException
     {
         // SETUP
-        final CompositeCacheAttributes cattr = new CompositeCacheAttributes();
-        cattr.setCacheName(CACHE_NAME);
-        cattr.setDiskUsagePattern( 
ICompositeCacheAttributes.DiskUsagePattern.SWAP );
+        final CompositeCacheAttributes cattr = 
CompositeCacheAttributes.defaults()
+                .withCacheName(CACHE_NAME)
+                
.withDiskUsagePattern(ICompositeCacheAttributes.DiskUsagePattern.SWAP);
 
         final IElementAttributes attr = new ElementAttributes();
 
diff --git 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/CompositeCacheManagerTest.java
 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/CompositeCacheManagerTest.java
index 811dae55..1560890e 100644
--- 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/CompositeCacheManagerTest.java
+++ 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/CompositeCacheManagerTest.java
@@ -39,7 +39,7 @@ class CompositeCacheManagerTest
         // create the manager
         final CompositeCacheManager manager = 
CompositeCacheManager.getInstance();
         // add a simple cache
-        final CompositeCacheAttributes cacheAttributes = new 
CompositeCacheAttributes();
+        final CompositeCacheAttributes cacheAttributes = 
CompositeCacheAttributes.defaults();
         final CompositeCache<String, String> cache = new 
CompositeCache<>(cacheAttributes, /* attr */ null);
         manager.addCache("simple_cache", cache);
         // add a client to the cache
diff --git 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/CompositeCacheUnitTest.java
 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/CompositeCacheUnitTest.java
index c9412fef..fd715aa7 100644
--- 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/CompositeCacheUnitTest.java
+++ 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/CompositeCacheUnitTest.java
@@ -55,9 +55,9 @@ class CompositeCacheUnitTest
         final String keyprefix2 = "MyPrefix2";
         final String cacheName = "testGetMatching_Normal";
         final String memoryCacheClassName = 
"org.apache.commons.jcs4.engine.memory.lru.LRUMemoryCache";
-        final CompositeCacheAttributes cattr = new CompositeCacheAttributes();
-        cattr.setMemoryCacheName( memoryCacheClassName );
-        cattr.setMaxObjects( maxMemorySize );
+        final CompositeCacheAttributes cattr = 
CompositeCacheAttributes.defaults()
+                .withMemoryCacheName(memoryCacheClassName)
+                .withMaxObjects(maxMemorySize);
 
         final IElementAttributes attr = new ElementAttributes();
 
@@ -105,10 +105,10 @@ class CompositeCacheUnitTest
         final int maxMemorySize = 0;
         final String cacheName = "testGetMatching_NotOnDisk";
         final String memoryCacheClassName = 
"org.apache.commons.jcs4.engine.memory.lru.LRUMemoryCache";
-        final CompositeCacheAttributes cattr = new CompositeCacheAttributes();
-        cattr.setCacheName(cacheName);
-        cattr.setMemoryCacheName( memoryCacheClassName );
-        cattr.setMaxObjects( maxMemorySize );
+        final CompositeCacheAttributes cattr = 
CompositeCacheAttributes.defaults()
+                .withCacheName(cacheName)
+                .withMemoryCacheName(memoryCacheClassName)
+                .withMaxObjects(maxMemorySize);
 
         final IElementAttributes attr = new ElementAttributes();
 
@@ -138,10 +138,10 @@ class CompositeCacheUnitTest
         final int maxMemorySize = 0;
         final String cacheName = "testGetMatching_NotOnDisk";
         final String memoryCacheClassName = 
"org.apache.commons.jcs4.engine.memory.lru.LRUMemoryCache";
-        final CompositeCacheAttributes cattr = new CompositeCacheAttributes();
-        cattr.setCacheName(cacheName);
-        cattr.setMemoryCacheName( memoryCacheClassName );
-        cattr.setMaxObjects( maxMemorySize );
+        final CompositeCacheAttributes cattr = 
CompositeCacheAttributes.defaults()
+                .withCacheName(cacheName)
+                .withMemoryCacheName(memoryCacheClassName)
+                .withMaxObjects(maxMemorySize);
 
         final IElementAttributes attr = new ElementAttributes();
 
@@ -171,8 +171,8 @@ class CompositeCacheUnitTest
         // SETUP
         final String cacheName = "testCacheName";
         final String mockMemoryCacheClassName = 
"org.apache.commons.jcs4.engine.memory.MockMemoryCache";
-        final CompositeCacheAttributes cattr = new CompositeCacheAttributes();
-        cattr.setMemoryCacheName( mockMemoryCacheClassName );
+        final CompositeCacheAttributes cattr = 
CompositeCacheAttributes.defaults()
+                .withMemoryCacheName(mockMemoryCacheClassName);
 
         final IElementAttributes attr = new ElementAttributes();
 
@@ -210,8 +210,8 @@ class CompositeCacheUnitTest
         // SETUP
         final String cacheName = "testCacheName";
         final String mockMemoryCacheClassName = 
"org.apache.commons.jcs4.engine.memory.MockMemoryCache";
-        final CompositeCacheAttributes cattr = new CompositeCacheAttributes();
-        cattr.setMemoryCacheName( mockMemoryCacheClassName );
+        final CompositeCacheAttributes cattr = 
CompositeCacheAttributes.defaults()
+                .withMemoryCacheName(mockMemoryCacheClassName);
 
         final IElementAttributes attr = new ElementAttributes();
 
diff --git 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/MockCompositeCacheManager.java
 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/MockCompositeCacheManager.java
index f3e6324a..e3d6d97b 100644
--- 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/MockCompositeCacheManager.java
+++ 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/control/MockCompositeCacheManager.java
@@ -72,7 +72,7 @@ public class MockCompositeCacheManager
         {
 //            System.out.println( "Creating mock cache" );
             final CompositeCache<K, V> newCache =
-                new CompositeCache<>( new CompositeCacheAttributes(), new 
ElementAttributes() );
+                new CompositeCache<>( CompositeCacheAttributes.defaults(), new 
ElementAttributes() );
             setCache( newCache );
         }
 
diff --git 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/fifo/FIFOMemoryCacheUnitTest.java
 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/fifo/FIFOMemoryCacheUnitTest.java
index e49258e2..28adde18 100644
--- 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/fifo/FIFOMemoryCacheUnitTest.java
+++ 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/fifo/FIFOMemoryCacheUnitTest.java
@@ -46,10 +46,10 @@ class FIFOMemoryCacheUnitTest
         final int maxObjects = 10;
         final String cacheName = "testExpirationPolicy_oneExtra";
 
-        final CompositeCacheAttributes attributes = new 
CompositeCacheAttributes();
-        attributes.setCacheName(cacheName);
-        attributes.setMaxObjects( maxObjects );
-        attributes.setSpoolChunkSize( 1 );
+        final CompositeCacheAttributes attributes = 
CompositeCacheAttributes.defaults()
+                .withCacheName(cacheName)
+                .withMaxObjects(maxObjects)
+                .withSpoolChunkSize(1);
 
         final FIFOMemoryCache<String, String> cache = new FIFOMemoryCache<>();
         cache.initialize( new CompositeCache<>( attributes, new 
ElementAttributes() ) );
@@ -82,10 +82,10 @@ class FIFOMemoryCacheUnitTest
         final int maxObjects = 10;
         final String cacheName = "testExpirationPolicy_oneExtra";
 
-        final CompositeCacheAttributes attributes = new 
CompositeCacheAttributes();
-        attributes.setCacheName(cacheName);
-        attributes.setMaxObjects( maxObjects );
-        attributes.setSpoolChunkSize( 1 );
+        final CompositeCacheAttributes attributes = 
CompositeCacheAttributes.defaults()
+                .withCacheName(cacheName)
+                .withMaxObjects(maxObjects)
+                .withSpoolChunkSize(1);
 
         final FIFOMemoryCache<String, String> cache = new FIFOMemoryCache<>();
         cache.initialize( new CompositeCache<>( attributes, new 
ElementAttributes() ) );
diff --git 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/lru/LHMLRUMemoryCacheUnitTest.java
 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/lru/LHMLRUMemoryCacheUnitTest.java
index 37620ac2..21c4e22e 100644
--- 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/lru/LHMLRUMemoryCacheUnitTest.java
+++ 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/lru/LHMLRUMemoryCacheUnitTest.java
@@ -61,7 +61,7 @@ class LHMLRUMemoryCacheUnitTest
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testClearThroughHub" );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max * 2;
 
         for ( int i = 0; i < items; i++ )
@@ -96,7 +96,7 @@ class LHMLRUMemoryCacheUnitTest
         final LHMLRUMemoryCache<String, String> mru = new 
LHMLRUMemoryCache<>();
         mru.initialize( cache );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max / 2;
 
         for ( int i = 0; i < items; i++ )
@@ -122,7 +122,7 @@ class LHMLRUMemoryCacheUnitTest
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testGetStatsThroughHub" );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max * 2;
 
         for ( int i = 0; i < items; i++ )
@@ -149,7 +149,7 @@ class LHMLRUMemoryCacheUnitTest
         throws CacheException
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testLoadFromCCF" );
-        final String memoryCacheName = 
cache.getCacheAttributes().getMemoryCacheName();
+        final String memoryCacheName = 
cache.getCacheAttributes().memoryCacheName();
         assertTrue( memoryCacheName.indexOf( "LHMLRUMemoryCache" ) != -1, 
"Cache name should have LHMLRU in it." );
     }
 
@@ -164,7 +164,7 @@ class LHMLRUMemoryCacheUnitTest
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testPutGetThroughHub" );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max * 2;
 
         for ( int i = 0; i < items; i++ )
@@ -219,7 +219,7 @@ class LHMLRUMemoryCacheUnitTest
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testPutGetThroughHubTwice" );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max * 2;
 
         for ( int i = 0; i < items; i++ )
@@ -260,7 +260,7 @@ class LHMLRUMemoryCacheUnitTest
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testPutRemoveThroughHub" );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max * 2;
 
         for ( int i = 0; i < items; i++ )
@@ -292,7 +292,7 @@ class LHMLRUMemoryCacheUnitTest
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testRemovePartialThroughHub" );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max / 2;
 
         cache.put( "test", "data" );
diff --git 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/mru/MRUMemoryCacheUnitTest.java
 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/mru/MRUMemoryCacheUnitTest.java
index 95b27d35..93b5da3b 100644
--- 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/mru/MRUMemoryCacheUnitTest.java
+++ 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/mru/MRUMemoryCacheUnitTest.java
@@ -61,7 +61,7 @@ class MRUMemoryCacheUnitTest
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testPutGetThroughHub" );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max * 2;
 
         for ( int i = 0; i < items; i++ )
@@ -96,7 +96,7 @@ class MRUMemoryCacheUnitTest
         final MRUMemoryCache<String, String> mru = new MRUMemoryCache<>();
         mru.initialize( cache );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max / 2;
 
         for ( int i = 0; i < items; i++ )
@@ -122,7 +122,7 @@ class MRUMemoryCacheUnitTest
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testGetStatsThroughHub" );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max * 2;
 
         for ( int i = 0; i < items; i++ )
@@ -149,7 +149,7 @@ class MRUMemoryCacheUnitTest
         throws CacheException
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testPutGet" );
-        final String memoryCacheName = 
cache.getCacheAttributes().getMemoryCacheName();
+        final String memoryCacheName = 
cache.getCacheAttributes().memoryCacheName();
         assertTrue( memoryCacheName.indexOf( "MRUMemoryCache" ) != -1, "Cache 
name should have MRU in it." );
     }
 
@@ -164,7 +164,7 @@ class MRUMemoryCacheUnitTest
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testPutGetThroughHub" );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max * 2;
 
         for ( int i = 0; i < items; i++ )
@@ -219,7 +219,7 @@ class MRUMemoryCacheUnitTest
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testPutGetThroughHub" );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max * 2;
 
         for ( int i = 0; i < items; i++ )
@@ -260,7 +260,7 @@ class MRUMemoryCacheUnitTest
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testPutGetThroughHub" );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max * 2;
 
         for ( int i = 0; i < items; i++ )
@@ -292,7 +292,7 @@ class MRUMemoryCacheUnitTest
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testGetStatsThroughHub" );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max / 2;
 
         cache.put( "test", "data" );
diff --git 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/shrinking/ShrinkerThreadUnitTest.java
 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/shrinking/ShrinkerThreadUnitTest.java
index 85f0bc29..76fea7c1 100644
--- 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/shrinking/ShrinkerThreadUnitTest.java
+++ 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/shrinking/ShrinkerThreadUnitTest.java
@@ -51,10 +51,10 @@ class ShrinkerThreadUnitTest
         throws IOException
     {
         // SETUP
-        final CompositeCacheAttributes cacheAttr = new 
CompositeCacheAttributes();
-        cacheAttr.setCacheName("testRegion");
-        cacheAttr.setMaxMemoryIdleTimeSeconds( 10 );
-        cacheAttr.setMaxSpoolPerRun( 10 );
+        final CompositeCacheAttributes cacheAttr = 
CompositeCacheAttributes.defaults()
+                .withCacheName("testRegion")
+                .withMaxMemoryIdleTimeSeconds(10)
+                .withMaxSpoolPerRun(10);
 
         final CompositeCache<String, String> cache = new 
CompositeCache<>(cacheAttr, new ElementAttributes());
 
@@ -88,10 +88,10 @@ class ShrinkerThreadUnitTest
         throws IOException
     {
         // SETUP
-        final CompositeCacheAttributes cacheAttr = new 
CompositeCacheAttributes();
-        cacheAttr.setCacheName("testRegion");
-        cacheAttr.setMaxMemoryIdleTimeSeconds( 10 );
-        cacheAttr.setMaxSpoolPerRun( 10 );
+        final CompositeCacheAttributes cacheAttr = 
CompositeCacheAttributes.defaults()
+                .withCacheName("testRegion")
+                .withMaxMemoryIdleTimeSeconds(10)
+                .withMaxSpoolPerRun(10);
 
         final CompositeCache<String, String> cache = new 
CompositeCache<>(cacheAttr, new ElementAttributes());
 
@@ -126,10 +126,10 @@ class ShrinkerThreadUnitTest
         throws IOException
     {
         // SETUP
-        final CompositeCacheAttributes cacheAttr = new 
CompositeCacheAttributes();
-        cacheAttr.setCacheName("testRegion");
-        cacheAttr.setMaxMemoryIdleTimeSeconds( 10 );
-        cacheAttr.setMaxSpoolPerRun( 10 );
+        final CompositeCacheAttributes cacheAttr = 
CompositeCacheAttributes.defaults()
+                .withCacheName("testRegion")
+                .withMaxMemoryIdleTimeSeconds(10)
+                .withMaxSpoolPerRun(10);
 
         final CompositeCache<String, String> cache = new 
CompositeCache<>(cacheAttr, new ElementAttributes());
 
@@ -163,10 +163,10 @@ class ShrinkerThreadUnitTest
         throws IOException
     {
         // SETUP
-        final CompositeCacheAttributes cacheAttr = new 
CompositeCacheAttributes();
-        cacheAttr.setCacheName("testRegion");
-        cacheAttr.setMaxMemoryIdleTimeSeconds( 10 );
-        cacheAttr.setMaxSpoolPerRun( 10 );
+        final CompositeCacheAttributes cacheAttr = 
CompositeCacheAttributes.defaults()
+                .withCacheName("testRegion")
+                .withMaxMemoryIdleTimeSeconds(10)
+                .withMaxSpoolPerRun(10);
 
         final CompositeCache<String, String> cache = new 
CompositeCache<>(cacheAttr, new ElementAttributes());
 
@@ -204,11 +204,11 @@ class ShrinkerThreadUnitTest
         throws Exception
     {
         // SETUP
-        final CompositeCacheAttributes cacheAttr = new 
CompositeCacheAttributes();
-        cacheAttr.setCacheName("testRegion");
-        
cacheAttr.setMemoryCacheName("org.apache.commons.jcs4.engine.memory.MockMemoryCache");
-        cacheAttr.setMaxMemoryIdleTimeSeconds( 1 );
-        cacheAttr.setMaxSpoolPerRun( 10 );
+        final CompositeCacheAttributes cacheAttr = 
CompositeCacheAttributes.defaults()
+                .withCacheName("testRegion")
+                
.withMemoryCacheName("org.apache.commons.jcs4.engine.memory.MockMemoryCache")
+                .withMaxMemoryIdleTimeSeconds(1)
+                .withMaxSpoolPerRun(10);
 
         final CompositeCache<String, String> cache = new 
CompositeCache<>(cacheAttr, new ElementAttributes());
         final MockMemoryCache<String, String> memory = 
(MockMemoryCache<String, String>)cache.getMemoryCache();
@@ -252,11 +252,11 @@ class ShrinkerThreadUnitTest
         throws Exception
     {
         // SETUP
-        final CompositeCacheAttributes cacheAttr = new 
CompositeCacheAttributes();
-        cacheAttr.setCacheName("testRegion");
-        
cacheAttr.setMemoryCacheName("org.apache.commons.jcs4.engine.memory.MockMemoryCache");
-        cacheAttr.setMaxMemoryIdleTimeSeconds( 1 );
-        cacheAttr.setMaxSpoolPerRun( 3 );
+        final CompositeCacheAttributes cacheAttr = 
CompositeCacheAttributes.defaults()
+                .withCacheName("testRegion")
+                
.withMemoryCacheName("org.apache.commons.jcs4.engine.memory.MockMemoryCache")
+                .withMaxMemoryIdleTimeSeconds(1)
+                .withMaxSpoolPerRun(3);
 
         final CompositeCache<String, String> cache = new 
CompositeCache<>(cacheAttr, new ElementAttributes());
         final MockMemoryCache<String, String> memory = 
(MockMemoryCache<String, String>)cache.getMemoryCache();
@@ -303,11 +303,11 @@ class ShrinkerThreadUnitTest
         throws Exception
     {
         // SETUP
-        final CompositeCacheAttributes cacheAttr = new 
CompositeCacheAttributes();
-        cacheAttr.setCacheName("testRegion");
-        
cacheAttr.setMemoryCacheName("org.apache.commons.jcs4.engine.memory.MockMemoryCache");
-        cacheAttr.setMaxMemoryIdleTimeSeconds( 1 );
-        cacheAttr.setMaxSpoolPerRun( 3 );
+        final CompositeCacheAttributes cacheAttr = 
CompositeCacheAttributes.defaults()
+                .withCacheName("testRegion")
+                
.withMemoryCacheName("org.apache.commons.jcs4.engine.memory.MockMemoryCache")
+                .withMaxMemoryIdleTimeSeconds(1)
+                .withMaxSpoolPerRun(3);
 
         final CompositeCache<String, String> cache = new 
CompositeCache<>(cacheAttr, new ElementAttributes());
         final MockMemoryCache<String, String> memory = 
(MockMemoryCache<String, String>)cache.getMemoryCache();
diff --git 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/soft/SoftReferenceMemoryCacheUnitTest.java
 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/soft/SoftReferenceMemoryCacheUnitTest.java
index 944e87f0..b38db7f2 100644
--- 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/soft/SoftReferenceMemoryCacheUnitTest.java
+++ 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/engine/memory/soft/SoftReferenceMemoryCacheUnitTest.java
@@ -72,7 +72,7 @@ class SoftReferenceMemoryCacheUnitTest
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testPutGetThroughHub" );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max * 2;
 
         for ( int i = 0; i < items; i++ )
@@ -107,7 +107,7 @@ class SoftReferenceMemoryCacheUnitTest
         final SoftReferenceMemoryCache<String, String> srmc = new 
SoftReferenceMemoryCache<>();
         srmc.initialize( cache );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max / 2;
 
         for ( int i = 0; i < items; i++ )
@@ -133,7 +133,7 @@ class SoftReferenceMemoryCacheUnitTest
         throws CacheException
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testPutGet" );
-        final String memoryCacheName = 
cache.getCacheAttributes().getMemoryCacheName();
+        final String memoryCacheName = 
cache.getCacheAttributes().memoryCacheName();
         assertTrue( memoryCacheName.indexOf( "SoftReferenceMemoryCache" ) != 
-1,
                     "Cache name should have SoftReference in it." );
     }
@@ -149,7 +149,7 @@ class SoftReferenceMemoryCacheUnitTest
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testPutGetThroughHub" );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max * 2;
 
         for ( int i = 0; i < items; i++ )
@@ -193,7 +193,7 @@ class SoftReferenceMemoryCacheUnitTest
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testPutGetThroughHub" );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max * 2;
 
         for ( int i = 0; i < items; i++ )
@@ -225,7 +225,7 @@ class SoftReferenceMemoryCacheUnitTest
     {
         final CacheAccess<String, String> cache = JCS.getInstance( 
"testGetStatsThroughHub" );
 
-        final int max = cache.getCacheAttributes().getMaxObjects();
+        final int max = cache.getCacheAttributes().maxObjects();
         final int items = max / 2;
 
         cache.put( "test", "data" );
diff --git 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/log/LogManagerUnitTest.java
 
b/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/log/LogManagerUnitTest.java
deleted file mode 100644
index 1ebb0a2c..00000000
--- 
a/commons-jcs4-core/src/test/java/org/apache/commons/jcs4/log/LogManagerUnitTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.apache.commons.jcs4.log;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-import org.junit.jupiter.api.Test;
-
-class LogManagerUnitTest
-{
-    @Test
-    void testLogFactoryDefault()
-    {
-        assertNotNull(Log.getLog(getClass()));
-    }
-}
diff --git 
a/commons-jcs4-core/src/test/test-conf/TestBlockDiskCacheSteadyLoad.ccf 
b/commons-jcs4-core/src/test/test-conf/TestBlockDiskCacheSteadyLoad.ccf
index 0d96d95c..90616ef0 100644
--- a/commons-jcs4-core/src/test/test-conf/TestBlockDiskCacheSteadyLoad.ccf
+++ b/commons-jcs4-core/src/test/test-conf/TestBlockDiskCacheSteadyLoad.ccf
@@ -21,7 +21,7 @@ jcs.default=DC
 
jcs.default.cacheattributes=org.apache.commons.jcs4.engine.CompositeCacheAttributes
 jcs.default.cacheattributes.MaxObjects=100
 
jcs.default.cacheattributes.MemoryCacheName=org.apache.commons.jcs4.engine.memory.lru.LRUMemoryCache
-jcs.default.cacheattributes.DiskUsagePatternName=UPDATE
+jcs.default.cacheattributes.DiskUsagePattern=UPDATE
 
 
 # AVAILABLE AUXILIARY CACHES
diff --git a/commons-jcs4-core/src/test/test-conf/TestDiskCacheSteadyLoad.ccf 
b/commons-jcs4-core/src/test/test-conf/TestDiskCacheSteadyLoad.ccf
index fd058295..cbe31e85 100644
--- a/commons-jcs4-core/src/test/test-conf/TestDiskCacheSteadyLoad.ccf
+++ b/commons-jcs4-core/src/test/test-conf/TestDiskCacheSteadyLoad.ccf
@@ -21,7 +21,7 @@ jcs.default=DC
 
jcs.default.cacheattributes=org.apache.commons.jcs4.engine.CompositeCacheAttributes
 jcs.default.cacheattributes.MaxObjects=100
 
jcs.default.cacheattributes.MemoryCacheName=org.apache.commons.jcs4.engine.memory.lru.LRUMemoryCache
-jcs.default.cacheattributes.DiskUsagePatternName=UPDATE
+jcs.default.cacheattributes.DiskUsagePattern=UPDATE
 
 
 # AVAILABLE AUXILIARY CACHES
diff --git a/commons-jcs4-core/src/test/test-conf/TestDiskCacheUsagePattern.ccf 
b/commons-jcs4-core/src/test/test-conf/TestDiskCacheUsagePattern.ccf
index e905c7e2..8ff31971 100644
--- a/commons-jcs4-core/src/test/test-conf/TestDiskCacheUsagePattern.ccf
+++ b/commons-jcs4-core/src/test/test-conf/TestDiskCacheUsagePattern.ccf
@@ -28,13 +28,13 @@ jcs.region.Swap=indexedDiskCache
 
jcs.region.Swap.cacheattributes=org.apache.commons.jcs4.engine.CompositeCacheAttributes
 jcs.region.Swap.cacheattributes.MaxObjects=100
 
jcs.region.Swap.cacheattributes.MemoryCacheName=org.apache.commons.jcs4.engine.memory.lru.LRUMemoryCache
-jcs.region.Swap.cacheattributes.DiskUsagePatternName=SWAP
+jcs.region.Swap.cacheattributes.DiskUsagePattern=SWAP
 
 jcs.region.Update=indexedDiskCache
 
jcs.region.Update.cacheattributes=org.apache.commons.jcs4.engine.CompositeCacheAttributes
 jcs.region.Update.cacheattributes.MaxObjects=100
 
jcs.region.Update.cacheattributes.MemoryCacheName=org.apache.commons.jcs4.engine.memory.lru.LRUMemoryCache
-jcs.region.Update.cacheattributes.DiskUsagePatternName=UPDATE
+jcs.region.Update.cacheattributes.DiskUsagePattern=UPDATE
 
 
 # #### AUXILIARY CACHES
diff --git a/commons-jcs4-core/src/test/test-conf/TestJCS-73.ccf 
b/commons-jcs4-core/src/test/test-conf/TestJCS-73.ccf
index 947c50ff..c31a7090 100644
--- a/commons-jcs4-core/src/test/test-conf/TestJCS-73.ccf
+++ b/commons-jcs4-core/src/test/test-conf/TestJCS-73.ccf
@@ -20,7 +20,7 @@ jcs.default=CACHE
 
jcs.default.cacheattributes=org.apache.commons.jcs4.engine.CompositeCacheAttributes
 jcs.default.cacheattributes.MaxObjects=-1
 
jcs.default.cacheattributes.MemoryCacheName=org.apache.commons.jcs4.engine.memory.lru.LRUMemoryCache
-jcs.default.cacheattributes.DiskUsagePatternName=UPDATE
+jcs.default.cacheattributes.DiskUsagePattern=UPDATE
 jcs.default.cacheattributes.UseMemoryShrinker=true
 jcs.default.cacheattributes.MaxMemoryIdleTimeSeconds=10
 jcs.default.cacheattributes.ShrinkerIntervalSeconds=10
diff --git a/xdocs/RegionProperties.xml b/xdocs/RegionProperties.xml
index b3a4b8d3..dd9392ee 100644
--- a/xdocs/RegionProperties.xml
+++ b/xdocs/RegionProperties.xml
@@ -136,7 +136,7 @@
                                                <td>30</td>
                                        </tr>
                                        <tr>
-                                               <td>DiskUsagePatternName</td>
+                                               <td>DiskUsagePattern</td>
                                                <td>
                                                        SWAP is the default. 
Under the swap pattern,
                                                        data is only put to 
disk when the max memory
diff --git a/xdocs/UpgradingFrom3x.xml b/xdocs/UpgradingFrom3x.xml
index eee4d729..77c5bfaa 100644
--- a/xdocs/UpgradingFrom3x.xml
+++ b/xdocs/UpgradingFrom3x.xml
@@ -103,6 +103,25 @@ 
jcs.default.cacheattributes=org.apache.commons.jcs4.engine.CompositeCacheAttribu
            Please note that several internals structures are not exported.
          </p>
       </subsection>
+      <subsection name="Changed Configuration Keys">
+        <p>
+           JCS 4.0.0 tries to pull some long-standing configuration 
inconsistencies straight.
+           The following configuration keys have been renamed or removed:
+
+           <table>
+               <tr>
+                   <th>Attribute Type</th>
+                   <th>Old Property Name</th>
+                   <th>New Property Name</th>
+               </tr>
+               <tr>
+                   <td>Region configuration (CompositeCacheAttributes)</td>
+                   <td>DiskUsagePatternName</td>
+                   <td>DiskUsagePattern</td>
+               </tr>
+            </table>
+         </p>
+      </subsection>
     </section>
   </body>
 </document>

Reply via email to