Contents

1 Preface
1.1 Version
1.2 Audience
1.3 Acknowledgements
1.4 About the Ehcache name and logo
2 Introduction
2.1 About Caches
2.2 Why caching works
2.2.1 Locality of Reference
2.2.2 The Long Tail
2.3 Will an Application Benefit from Caching?
2.3.1 Speeding up CPU bound Applications
2.3.2 Speeding up I/O bound Applications
2.3.3 Increased Application Scalability
2.4 How much will an application speed up with Caching?
2.4.1 The short answer
2.4.2 Applying Amdahl's Law
2.4.2.1 Persistent Object Relational Caching
2.4.2.2 Web Page Caching
2.4.2.3 Web Page Fragment Caching
2.4.3 Cache Efficiency
2.4.4 Cluster Efficiency
2.4.5 A cache version of Amdahl's law
2.4.6 Web Page example
3 Getting Started
3.1 General Purpose Caching
3.2 Hibernate
3.3 Java EE Servlet Caching
3.4 RESTful and SOAP Caching with the Cache Server
3.5 JCache style caching
3.6 Spring, Cocoon, Acegi and other frameworks
4 Features
5 %toc|fromDepth=2|toDepth=3
5.1 Fast and Light Weight
5.1.1 Fast
5.1.2 Simple
5.1.3 Small foot print
5.1.4 Minimal dependencies
5.2 Scalable
5.2.1 Provides Memory and Disk stores for scalabilty into gigabytes
5.2.2 Scalable to hundreds of caches
5.2.3 Tuned for high concurrent load on large multi-cpu servers
5.2.4 Multiple CacheManagers per virtual machine
5.3 Flexible
5.3.1 Supports Object or Serializable caching
5.3.2 Support cache-wide or Element-based expiry policies
5.3.3 Provides LRU, LFU and FIFO cache eviction policies
5.3.4 Provides Memory and Disk stores
5.3.5 Distributed
5.3.6 Dynamic, Runtime Configuration of Caches
5.4 Standards Based
5.4.1 Full implementation of JSR107 JCACHE API
5.5 Extensible
5.5.1 Listeners may be plugged in
5.5.2 Peer Discovery, Replicators and Listeners may be plugged in
5.5.3 Cache Extensions may be plugged in
5.5.4 Cache Loaders may be plugged in
5.5.5 Cache Exception Handlers may be plugged in
5.6 Application Persistence
5.6.1 Persistent disk store which stores data between VM restarts
5.6.2 Flush to disk on demand
5.7 Listeners
5.7.1 CacheManager listeners
5.7.2 Cache event listeners
5.8 JMX Enabled
5.9 Distributed Caching
5.9.1 Support for replication via RMI or JGroups
5.9.2 Peer Discovery
5.9.3 Reliable Delivery
5.9.4 Synchronous Or Asynchronous Replication
5.9.5 Copy Or Invalidate Replication
5.9.6 Transparent Replication
5.9.7 Extensible
5.9.8 Bootstrapping from Peers
5.10 Cache Server
5.10.1 RESTful cache server
5.10.2 SOAP cache server
5.10.3 comes as a WAR or as a complete server
5.11 Java EE and Applied Caching
5.11.1 Blocking Cache to avoid duplicate processing for concurrent operations
5.11.2 SelfPopulating Cache for pull through caching of expensive operations
5.11.3 Java EE Gzipping Servlet Filter
5.11.4 Cacheable Commands
5.11.5 Works with Hibernate
5.11.6 Works with Google App Engine
5.11.7 Transactional support through JTA
5.12 High Quality
5.12.1 High Test Coverage
5.12.2 Automated Load, Limit and Performance System Tests
5.12.3 Specific Concurrency Testing
5.12.4 Production tested
5.12.5 Fully documented
5.12.6 Trusted by Popular Frameworks
5.12.7 Conservative Commit policy
5.12.8 Full public information on the history of every bug
5.12.9 Responsiveness to serious bugs
5.13 Open Source Licensing
5.13.1 Apache 2.0 license
6 Key Ehcache Concepts
6.1 Key Ehcache Classes
6.1.1 CacheManager
6.1.1.1 CacheManager Creation Modes
6.1.1.1.1 Singleton Mode
6.1.1.1.2 Instance Mode
6.1.1.1.3 Mixed Singleton and Instance Mode
6.1.2 Ehcache
6.1.3 Element
6.2 Cache Usage Patterns
6.2.1 Direct Manipulation
6.2.2 Self Populating
7 Architecture
8 Cache Configuration
8.1 ehcache.xsd
8.2 ehcache-failsafe.xml
8.3 ehcache.xml and other configuration files
8.4 Special System Properties
8.4.1 net.sf.ehcache.disabled
8.4.2 net.sf.ehcache.use.classic.lru
9 Storage Options
9.1 Memory Store
9.1.1 Memory Use, Spooling and Expiry Strategy
9.2 DiskStore
9.2.1 DiskStores are Optional
9.2.1.1 Turning off disk stores
9.2.2 Suitable Element Types
9.2.3 Storage
9.2.3.1 Files
9.2.3.2 Storage Location
9.2.3.3 diskStore Element
9.2.4 Expiry
9.2.5 Eviction
9.2.6 Serializable Objects
9.2.7 Safety
9.2.8 Persistence
10 Cache Eviction Algorithms
10.1 Eviction
10.1.1 Supported MemoryStore Eviction Algorithms
10.1.2 MemoryStore Eviction Algorithms
10.1.2.1 Least Recently Used (LRU)
10.1.2.2 Less Frequently Used (LFU)
10.1.2.3 First In First Out (FIFO)
10.1.3 DiskStore Eviction Algorithms
11 Code Samples
12 %toc|fromDepth=2|toDepth=3
12.1 Using the CacheManager
12.1.1 Singleton versus Instance
12.1.2 Ways of loading Cache Configuration
12.1.3 Adding and Removing Caches Programmatically
12.1.4 Shutdown the CacheManager
12.2 Creating Caches Programmatically
12.2.1 Creating a new cache from defaults
12.2.2 Creating a new cache with custom parameters
12.3 Using Caches
12.3.1 Obtaining a reference to a Cache
12.3.2 Performing CRUD operations
12.3.3 Disk Persistence on demand
12.3.4 Obtaining Cache Sizes
12.3.5 Obtaining Statistics of Cache Hits and Misses
12.3.6 JTA
12.4 Dynamically Modifying Cache Configurations
12.5 Registering CacheStatistics in an MBeanServer
12.6 Browse the JUnit Tests
12.7 JCache Examples
12.8 Terracotta Example
12.9 Cache Server Examples
13 Java Requirements and Dependencies
13.1 Java Requirements
13.2 Mandatory Dependencies
14 Logging
14.1 SLF4J Logging
14.1.1 Concrete Logging Implementation Use in Maven
14.1.2 Concrete Logging Implemenation Use in the Download Kit
14.2 Recommended Logging Levels
15 Remote Network debugging and monitoring for Distributed Caches
15.1 Introduction
15.2 Packaging
15.3 Limitations
15.4 Usage
15.4.1 Output
15.4.2 Providing more Detailed Logging
15.4.3 Yes, but I still have a cluster problem
16 Tuning Garbage Collection
16.1 Detecting Garbage Collection Problems
16.2 Garbage Collection Tuning
16.3 Distributed Caching Garbage Collection Tuning
17 JMX Management and Monitoring
17.1 Terracotta Monitoring Products
17.2 JMX Overview
17.3 MBeans
17.4 JMX Remoting
17.5 ObjectName naming scheme
17.6 The Management Service
17.7 JConsole Example
17.8 Hibernate statistics
17.9 JMX Tutorial
18 JTA
18.1 Transaction Managers
18.1.1 Automatically Detected Transaction Managers
18.1.2 Configuring a Transaction Manager
18.2 Configuring a Cache for JTA
18.3 Using a JTA Cache
18.3.1 All or nothing
18.3.2 Change Visibility
18.3.3 Write-behind and Write-through
18.4 Architecture
18.4.1 Bootstrapping
18.4.2 A day in the life of a transactional Cache
18.5 Failure
18.5.1 Recovery
18.6 Sample Apps
18.6.1 JTA Sample App
18.6.2 JTA Banking Application
18.6.3 Examinator
18.7 Limitations
18.7.1 Terracotta Clusters only
18.7.2 Hibernate Transactions
18.8 FAQ
18.8.1 How do I make WebLogic 10 work with Ehcache JTA?
19 Ehcache Monitor
20 %toc|fromDepth=2|toDepth=2
20.1 Installation And Configuration
20.1.1 Probe
20.1.2 Monitor
20.2 Using the Web GUI
20.2.1 Cache Managers
20.2.2 Statistics
20.2.3 Configuration
20.2.4 Contents
20.3 Using the API
20.4 Known Issues
20.4.1 Internet Explorer
20.5 Licensing
21 Bulk Loading
22 %toc|fromDepth=2|toDepth=2
22.1 Uses
22.2 API
22.2.1 setNodeCoherence(boolean mode)
22.2.2 isNodeCoherent()
22.2.3 isClusterCoherent()
22.2.4 waitUntilClusterCoherent()
22.3 Speed Improvement
22.4 FAQ
22.4.1 Why does the bulk loading mode only apply to Terracotta clusters?
22.4.2 How does bulk load with RMI distributed caching work?
22.5 Performance Tips
22.5.1 When to use Multiple Put Threads
22.5.2 Bulk Loading on Multiple Nodes
22.5.3 Why not run in bulk load mode all the time
22.6 Download
22.7 Further Information
23 Class loading and Class Loaders
23.1 Plugin class loading
23.2 Loading of ehcache.xml resources
23.3 Classloading with Terracotta clustering
24 Performance Considerations
24.1 DiskStore
24.2 Replication
24.3 Statistics
25 Cache Decorators
25.1 Creating a Decorator
25.2 Accessing the decorated cache
25.2.1 Using CacheManager to access decorated caches
25.3 Built-in Decorators
25.3.1 BlockingCache
25.3.2 SelfPopulatingCache
25.3.3 Caches with Exception Handling
26 Hibernate Second Level Cache
27 %toc|fromDepth=2|toDepth=2
27.1 Download
27.2 Important Notice if Upgrading from Terracotta or Ehcache prior to 2.0
27.3 Quick Start
27.4 Setting Ehcache as the Hibernate Second Level Cache
27.4.1 Hibernate 3.3 and higher
27.4.2 Hibernate 3.0 - 3.2
27.4.3 Configuring the Ehcache Hibernate caches
27.4.4 Programmatic setting of the Hibernate Cache Provider
27.5 Configuring Hibernate for Caching
27.5.1 Definition of the different cache strategies
27.5.1.1 read-only
27.5.1.2 nonstrict-read-write
27.5.1.3 read-write
27.6 Configuring ehcache.xml
27.6.1 Domain Objects
27.6.2 Hibernate
27.6.3 Collections
27.6.4 Hibernate CacheConcurrencyStrategy
27.6.5 Queries
27.6.6 StandardQueryCache
27.6.7 UpdateTimestampsCache
27.6.8 Named Query Caches
27.6.9 Using Query Caches
27.6.10 Hibernate CacheConcurrencyStrategy
27.7 Demo Apps
27.7.1 Hibernate Tutorial
27.7.2 Examinator
27.8 FAQ
27.8.1 Should I use the provider in the Hibernate distribution or in Ehcache?
27.8.2 What is the relationship between the Hibernate and Ehcache projects?
27.8.3 Does Ehcache support the new Hibernate 3.3 2nd level caching SPI?
27.8.4 Does Ehcache support the transactional strategy?
27.8.5 Is Ehcache Cluster Safe?
27.8.6 How are Hibernate Entities keyed?
27.8.7 Can you use Identity mode with the Terracotta Server Array
27.8.8 I get org.hibernate.cache.ReadWriteCache - An item was expired by the cache while it was locked error messages. What is it?
27.9 Performance Tips
27.9.1 Session.load
27.9.2 Session.find and Query.find
27.9.3 Session.iterate and Query.iterate
27.10 How to Scale
28 Shutting Down Ehcache
28.1 ServletContextListener
28.2 The Shutdown Hook
28.2.1 When to use the shutdown hook
28.2.2 What the shutdown hook does
28.2.3 When a shutdown hook will run, and when it will not
28.3 Dirty Shutdown
29 Web Caching
29.1 SimplePageCachingFilter
29.2 Keys
29.3 Configuring the cacheName
29.4 Concurent Cache Misses
29.5 Gzipping
29.6 Caching Headers
29.7 Init-Params
29.8 Reentrance
29.9 SimplePageFragmentCachingFilter
29.10 Example web.xml configuration
29.11 CachingFilter Exceptions
29.11.1 FilterNonReentrantException
29.11.2 AlreadyGzippedException
29.11.3 ResponseHeadersNotModifiableException
30 Distributed Caching Options
30.1 Pluggable Mechanisms
30.2 The need for shared cache data
30.3 Replicated Caches
30.4 Using a Cache Server
30.5 Notification Strategies
30.6 Potential Issues with Distributed Caching
30.6.1 Potential for Inconsistent Data
30.6.1.1 Synchronous Delivery
30.6.1.2 Put and Update via Invalidation
30.6.2 Use of Time To Idle
31 Distributed Caching Using Terracotta Server Array
31.1 Architecture
31.2 Worked Example
31.3 Terracotta Configuration
31.3.1 CacheManager Configuration
31.3.2 Terracotta Server Configuration
31.3.2.1 Specification of a source of configuration
31.3.2.2 Specification using embedded tc-config
31.3.3 Enabling Terracotta clustering per cache
31.4 Copy On Read
31.5 Behaviour differences with CacheEventListeners when using Terracotta Clustering
31.5.1 Cache listeners
31.5.2 Overflow to Disk
31.6 Cluster Topology New feature in Ehcache 2.0
31.7 Terracotta Cluster Events New feature in Ehcache 2.0
31.7.1 Example Code
31.7.2 Uses for Cluster Events
31.8 More Information
31.9 FAQ
31.9.1 Is Expiry the same in Terracotta?
31.9.2 What Eviction strategies are supported?
31.9.3 What Stores are available and how are they configured?
31.9.4 When do Elements overflow?
31.9.5 How does Element equality work in Serialization mode?
31.9.6 How does Element equality work in Identity mode?
31.9.7 What is the recommended way to write to a database?
31.9.8 If updates to a database bypass the Terracotta clustered application, then how is that coherent?
31.9.9 Do CacheEventListeners work?
31.9.10 What are the JMX statistics available in the Terracotta Developer Console?
31.9.11 What classloader is used to deserialize clustered objects in valueMode="serialization"?
31.9.12 What versions of Ehcache and Terracotta work together?
31.9.13 What happens when an L1 (i.e. an Ehcache node) disconnects from the L2 (i.e. the Terracotta Server Array)?
32 RMI Distributed Caching
32.1 Suitable Element Types
32.2 Configuring the Peer Provider
32.2.1 Peer Discovery
32.2.2 Automatic Peer Discovery
32.2.2.1 Example
32.2.3 Manual Peer Discovery
32.2.3.1 Example
32.3 Configuring the CacheManagerPeerListener
32.4 Configuring Cache Replicators
32.5 Configuring Bootstrap from a Cache Peer
32.6 Full Example
32.7 Common Problems
32.7.1 Tomcat on Windows
32.7.2 Multicast Blocking
32.7.3 Multicast Not Propagating Far Enough or Propagating Too Far
33 Distributed Caching using JGroups
33.1 Suitable Element Types
33.2 Peer Discovery
33.3 Configuration
33.4 Example configuration using UDP Multicast
33.5 Example configuration using TCP Unicast
33.6 Protocol considerations.
33.7 Configuring CacheReplicators
33.8 Complete Sample configuration
33.9 Common Problems
34 Distributed Caching using JMS
34.1 Ehcache Replication and External Publishers
34.1.1 Configuration
34.1.1.1 Message Queue Configuration
34.1.1.2 Ehcache Configuration
34.1.1.2.1 Configuring the JMSCacheManagerPeerProviderFactory
34.1.1.2.2 Example Configurations
34.1.1.2.3 Configuring the JMSCacheManagerPeerProviderFactory for Active MQ
34.1.1.2.4 Configuring the JMSCacheManagerPeerProviderFactory for Open MQ
34.1.1.2.5 Configuring the JMSCacheReplicatorFactory
34.1.2 External JMS Publishers
34.1.2.1 Required Message Properties
34.1.2.1.1 cacheName Property
34.1.2.1.2 action Property
34.1.2.1.3 mimeType Property
34.1.2.1.4 key Property
34.1.2.2 Code Samples
34.1.2.3 PUT a Java Object into an Ehcache JMS Cluster
34.1.2.4 PUT XML into an Ehcache JMS Cluster
34.1.2.5 PUT arbitrary bytes into an Ehcache JMS Cluster
34.1.2.6 REMOVE
34.1.2.7 REMOVE_ALL
34.2 Using the JMSCacheLoader
34.2.1 Example Configuration Using Active MQ
34.2.2 Example Configuration Using Open MQ
34.3 Configuring Clients for Message Queue Reliability
34.4 Tested Message Queues
34.4.1 Sun Open MQ
34.4.2 Active MQ
34.4.3 Oracle AQ
34.4.4 JBoss Queue
34.5 Known JMS Issues
34.5.1 Active MQ Temporary Destinatons
34.5.2 WebSphere 5 and 6
35 BlockingCache and SelfPopulatingCache
35.1 Blocking Cache
35.2 SelfPopulatingCache
36 CacheManager Event Listeners
36.1 Configuration
36.2 Implementing a CacheManagerEventListenerFactory and CacheManagerEventListener
37 Cache Loaders
37.1 Declarative Configuration
37.2 Implementing a CacheLoaderFactory and CacheLoader
37.3 Programmatic Configuration
38 Cache Event Listeners
38.1 Configuration
38.2 Implementing a CacheEventListenerFactory and CacheEventListener
39 Cache Exception Handlers
39.1 Declarative Configuration
39.2 Implementing a CacheExceptionHandlerFactory and CacheExceptionHandler
39.3 Programmatic Configuration
40 Cache Extensions
40.1 Declarative Configuration
40.2 Implementing a CacheExtensionFactory and CacheExtension
40.3 Programmatic Configuration
41 Cache Server
41.1 Introduction
41.2 RESTful Web Services
41.2.1 RESTFul Web Services API
41.2.2 CacheManager Resource Operations
41.2.2.1 OPTIONS /{cache}}
41.2.2.2 GET /
41.2.3 Cache Resource Operations
41.2.3.1 OPTIONS /{cache}}
41.2.3.2 HEAD /{cache}}
41.2.3.3 GET /{cache}
41.2.3.4 PUT /{cache}
41.2.3.5 DELETE / {cache}
41.2.4 Element Resource Operations
41.2.4.1 OPTIONS /{cache}}
41.2.4.2 HEAD /{cache}/{element}
41.2.4.3 GET /{cache}/{element}
41.2.4.4 HEAD /{cache}/{element}
41.2.4.5 PUT /{cache}/{element}
41.2.4.6 DELETE / {cache}/{element}
41.2.5 Resource Representations
41.2.5.1 Element Resource Representations
41.2.6 RESTful Code Samples
41.2.6.1 Curl Code Samples
41.2.6.1.1 OPTIONS
41.2.6.1.2 HEAD
41.2.6.1.3 PUT
41.2.6.1.4 GET
41.2.6.2 Ruby Code Samples
41.2.6.2.1 GET
41.2.6.3 Python Code Samples
41.2.6.3.1 GET
41.2.6.4 Java Code Samples
41.2.6.4.1 Create and Get a Cache and Entry
41.2.6.5 Scala Code Samples
41.2.6.5.1 GET
41.2.6.6 PHP Code Samples
41.2.6.6.1 GET
41.2.6.6.2 PUT
41.3 Creating Massive Caches with Load Balancers and Partitioning
41.3.1 Non-redundant, Scalable with client hash-based routing
41.3.2 Redundant, Scalable with client hash-based routing
41.3.3 Redundant, Scalable with load balancer hash-based routing
41.4 W3C (SOAP) Web Services
41.4.1 W3C Web Services API
41.4.2 Security
41.5 Requirements
41.5.1 Java
41.5.2 Web Container (WAR packaged version only)
41.6 Downloading
41.6.1 Sourceforge
41.6.2 Maven
41.7 Installation
41.7.1 Installing the WAR
41.7.2 Configuring the Web Application
41.7.2.1 Disabling the RESTful Web Service
41.7.2.2 Disabling the SOAP Web Service
41.7.2.3 Configuring Caches
41.7.2.4 SOAP Web Service Security
41.8 Installing the Standalone Server
41.8.1 Configuring the Standalone Server
41.8.2 Starting and Stopping the Standalone Server
41.8.2.1 Using Commons Daemon jsvc
41.8.2.2 Executable jar
41.9 Monitoring
41.9.1 Remotely Monitoring the Standalone Server with JMX
41.10 Download
42 Explicit Locking API
43 %toc|fromDepth=2|toDepth=2
43.1 Locking Modes
43.1.1 Standalone Ehcache
43.1.2 Standard Ehcache clustered with Terracotta
43.1.3 Explicit Locking Ehcache clustered with Terracotta
43.2 How it works
43.3 How to Scale
43.4 Download
44 Write-through and Write-behind Caching with the CacheWriter
44.1 Potential Benefits of Write-Behind
44.2 Limitations & Constraints of Write-Behind
44.2.1 Transaction Boundaries
44.2.2 Time delay
44.2.3 Applications Tolerant of Inconsistency
44.2.4 Node time synchronisation
44.2.5 No ordering guarantees
44.3 Using a combined Read-Through and Write-Behind Cache
44.3.1 Lazy Loading
44.3.2 Caching of a Partial Dataset
44.3.2.1 Eviction
44.3.2.2 Expiry
44.4 Ehcache Versions
44.4.1 Ehcache DX (Standalone Ehcache)
44.4.2 Ehcache EX and FX
44.4.2.1 Durable HA write-behind Queue
44.4.2.2 Cluster wide queue processing
44.5 Configuration
44.5.1 Configuration Attributes
44.5.1.1 All modes
44.5.1.2 write-through mode only
44.5.1.3 write-behind mode only
44.6 API
44.7 SPI
45 OpenJPA Caching Provider
45.1 Installing
45.2 Configuration
45.3 Default Cache
46 Grails: Using Ehcache as a Second Level Caching Provider for Hibernate within Grails
46.1 Configuring Ehcache as the second level Hibernate cache
46.2 Overriding defaults by specifying cache configurations
46.3 Futher information
47 JSR107 (JCACHE) Support
47.1 JSR107 Implementation
47.2 Using JCACHE
47.2.1 Creating JCaches
47.2.1.1 Creating a JCache using an Ehcache decorator
47.2.1.2 Creating a JCache from an existing Cache in Ehcache's CacheManager
47.2.1.3 Adding a JCache to Ehcache's CacheManager
47.2.1.4 Creating a JCache using the JCache CacheManager
47.2.2 Getting a JCache
47.2.3 Using a JCache
47.3 Problems and Limitations in the early draft of JSR107
47.3.1 net.sf.jsr107cache.CacheManager
47.3.2 net.sf.jsr107cache.CacheFactory
47.3.3 net.sf.jsr107cache.Cache
47.3.4 net.sf.jsr107cache.CacheEntry
47.3.5 net.sf.jsr107cache.CacheStatistics
47.3.6 net.sf.jsr107cache.CacheListener
47.3.7 net.sf.jsr107cache.CacheLoader
47.4 Other Areas
47.4.1 JMX
48 Glassfish How To & FAQ
48.1 Versions
48.2 HowTo
48.2.1 HowTo Get A Sample Application using Ehcache packaged and Deployed to Glassfish
48.2.2 How to get around the EJB Container restrictions on thread creation
48.3 Glassfish FAQ
48.3.1 Ehcache page caching versions below Ehcache 1.3 get an IllegalStateException in Glassfish.
48.3.2 I get a Could not ungzip. Heartbeat will not be working. Not in GZIP format reported from PayloadUtil exception when using Ehcache with my Glassfish cluster. Why?
49 Google App Engine How To
49.1 Why?
49.2 Compatibility
49.3 Limitations
49.4 Versions
49.5 Configuring ehcache.xml
49.6 Recipes
49.6.1 Setting up Ehcache as a local cache in front of memcacheg
49.6.2 Using memcacheg in place of a DiskStore
49.6.3 Distributed Caching
49.6.4 Dynamic Web Content Caching
49.7 Google App Engine FAQ
49.7.1 I get an error java.lang.NoClassDefFoundError: java.rmi.server.UID is a restricted class
50 Tomcat Issues and Best Practices
50.1 Tomcat Known Issues
50.1.1 Problem rejoining a cluster after a reload
50.1.2 In development, there appear to be class loader memory leak as I continually redeploy my web application.
50.1.3 net.sf.ehcache.CacheException: Problem starting listener for RMICachePeer ...
50.1.4 Multiple Host Entries in Tomcat's server.xml stops replication from occurring
51 Building from Source
51.1 Building an Ehcache distribution from source
51.2 Running Tests for Ehcache
51.3 Deploying Maven Artifacts
51.4 Building the Site
51.5 Deploying a release
51.5.1 Maven Release
51.5.2 Sourceforge Release
52 Frequently Asked Questions
52.1 Does Ehcache run on JDK1.3/JDK1.4?
52.2 Can you use more than one instance of Ehcache in a single VM?
52.3 Can you use Ehcache with Hibernate and outside of Hibernate at the same time?
52.4 What happens when maxElementsInMemory is reached? Are the oldest items are expired when new ones come in?
52.5 Is it thread safe to modify Element values after retrieval from a Cache?
52.6 Can non-Serializable objects be stored in a cache?
52.7 Why is there an expiry thread for the DiskStore but not for the MemoryStore?
52.8 What elements are mandatory in ehcache.xml?
52.9 Can I use Ehcache as a memory cache only?
52.10 Can I use Ehcache as a disk cache only?
52.11 Where is the source code? The source code is distributed in the root directory of the download.
52.12 How do you get statistics on an Element without affecting them?
52.13 How do you get WebSphere to work with ehcache?
52.14 Do you need to call CacheManager.getInstance().shutdown() when you finish with ehcache?
52.15 Can you use Ehcache after a CacheManager.shutdown()?
52.16 I have created a new cache and its status is STATUS_UNINITIALISED. How do I initialise it?
52.17 Is there a simple way to disable Ehcache when testing?
52.18 How do I dynamically change Cache attributes at runtime?
52.19 I get net.sf.ehcache.distribution.RemoteCacheException: Error doing put to remote peer. Message was: Error unmarshaling return header; nested exception is: java.net.SocketTimeoutException: Read timed out. What does this mean.
52.20 Should I use this directive when doing distributed caching? cacheManagerEventListenerFactory class="" properties=""/
52.21 What is the minimum config to get distributed caching going?
52.22 How can I see if distributed caching is working?
52.23 Why can't I run multiple applications using Ehcache on one machine?
52.24 How many threads does Ehcache use, and how much memory does that consume?
52.25 I am using Tomcat 5, 5.5 or 6 and I am having a problem. What can I do?
52.26 I am using Java 6 and getting a java.lang.VerifyError on the Backport Concurrent classes. Why?
52.27 How do I get a memory only cache to persist to disk between VM restarts?
52.28 I get a javax.servlet.ServletException: Could not initialise servlet filter when using SimplePageCachingFilter. Why?
52.29 I see, in my application's log:
52.30 How do I add a CacheReplicator to a cache that already exists? The cache event listening works but it does not get plumbed into the peering mechanism.
52.31 I am using the RemoteDebugger to monitor cluster messages but all I see is "Cache size: 0"
52.32 With distributed replication on Ubuntu or Debian, I see the following warning,
52.33 I see log messages about SoftReferences. What are these about and how do I stop getting the messages?
52.34 My Hibernate Query caches entries are replicating but the other caches in the cluster are not using them.
52.35 Active MQ Temporary Destinatons
52.36 Is Ehcache compatible with Google App Engine?
52.37 Can my app server use JMS Replication?
52.38 Why does Ehcache 1.6 use more memory than 1.5?
Index

1 PrefaceContents

This is a book about Ehcache, a widely used open source Java cache. Ehcache has grown in size and scope since it was introduced in October 2003. As people used it they often noticed it was missing a feature they wanted. Over time, the features that were repeatedly asked for, and make sense for a Cache, have been added.

Ehcache is now used for Hibernate caching, data access object caching, security credential caching, web caching, SOAP and RESTful server caching, application persistence and distributed caching.

In August 2009, Ehcache was acquired by Terracotta, Inc.

1.1 VersionContents

This book is for Ehcache version 1.7.1.

1.2 AudienceContents

The intended audience for this book is developers who use ehcache. It should be able to be used to start from scratch, get up and running quickly, and also be useful for the more complex options.

Ehcache is about performance and load reduction of underlying resources. Another natural audience is performance specialists.

It is also intended for application and enterprise architects. Some of the features of ehcache, such as distributed caching and Java EE caching, are alternatives to be considered along with other ways of solving those problems. This book discusses the trade-offs in Ehcache's approach to help make a decision about appropriateness of use.

1.3 AcknowledgementsContents

Ehcache has had many contributions in the form of forum discussions, feature requests, bug reports, patches and code commits.

Rather than try and list the many hundreds of people who have contributed to Ehcache in some way it is better to link to the web site where contributions are acknowledged in the following ways:

1.4 Contents

images/ehcache_logo

Adam Murdoch (an all round top Java coder) came up with the name in a moment of inspiration while we were stuck on the SourceForge project create page. Ehcache is a palindrome. He thought the name was wicked cool and we agreed.

The logo is similarly symmetrical, and is evocative of the diagram symbol for a doubly-linked list. That structure lies at the heart of ehcache.

--- Introduction ---

2 IntroductionContents

Ehcache is a cache library. Before getting into ehcache, it is worth stepping back and thinking about caching generally.

2.1 About CachesContents

Wiktionary defines a cache as A store of things that will be required in future, and can be retrieved rapidly. That is the nub of it.

In computer science terms, a cache is a collection of temporary data which either duplicates data located elsewhere or is the result of a computation. Once in the cache, the data can be repeatedly accessed inexpensively.

2.2 Why caching worksContents

2.2.1 Locality of ReferenceContents

While Ehcache concerns itself with Java objects, caching is used throughout computing, from CPU caches to the DNS system. Why? Because many computer systems exhibit locality of reference. Data that is near other data or has just been used is more likely to be used again.

2.2.2 The Long TailContents

Chris Anderson, of Wired Magazine, coined the term The Long Tail to refer to Ecommerce systems. The idea that a small number of items may make up the bulk of sales, a small number of blogs might get the most hits and so on. While there is a small list of popular items, there is a long tail of less popular ones.

images/longtail

The Long Tail

The Long Tail is itself a vernacular term for a Power Law probability distribution. They don't just appear in ecommerce, but throughout nature. One form of a Power Law distribution is the Pareto distribution, commonly know as the 80:20 rule.

This phenomenon is useful for caching. If 20% of objects are used 80% of the time and a way can be found to reduce the cost of obtaining that 20%, then the system performance will improve.

2.3 Will an Application Benefit from Caching?Contents

The short answer is that it often does, due to the effects noted above.

The medium answer is that it often depends on whether it is CPU bound or I/O bound. If an application is I/O bound then then the time taken to complete a computation depends principally on the rate at which data can be obtained. If it is CPU bound, then the time taken principally depends on the speed of the CPU and main memory.

While the focus for caching is on improving performance, it it also worth realizing that it reduces load. The time it takes something to complete is usually related to the expense of it. So, caching often reduces load on scarce resources.

2.3.1 Speeding up CPU bound ApplicationsContents

CPU bound applications are often sped up by:

2.3.2 Speeding up I/O bound ApplicationsContents

Many applications are I/O bound, either by disk or network operations. In the case of databases they can be limited by both.

There is no Moore's law for hard disks. A 10,000 RPM disk was fast 10 years ago and is still fast. Hard disks are speeding up by using their own caching of blocks into memory.

Network operations can be bound by a number of factors:

2.3.3 Increased Application ScalabilityContents

The flip side of increased performance is increased scalability. Say you have a database which can do 100 expensive queries per second. After that it backs up and if connections are added to it it slowly dies.

In this case, caching may be able to reduce the workload required. If caching can cause 90 of that 100 to be cache hits and not even get to the database, then the database can scale 10 times higher than otherwise.

2.4 How much will an application speed up with Caching?Contents

2.4.1 The short answerContents

The short answer is that it depends on a multitude of factors being:

The long answer, unfortunately, is complicated and mathematical. It is considered next.

2.4.2 Applying Amdahl's LawContents

Amdahl's law, after Gene Amdahl, is used to find the system speed up from a speed up in part of the system.

    1 / ((1 - Proportion Sped Up) + Proportion Sped Up / Speed up)

The following examples show how to apply Amdahl's law to common situations. In the interests of simplicity, we assume:

2.4.2.1 Persistent Object Relational Caching

A Hibernate Session.load() for a single object is about 1000 times faster from cache than from a database.

A typical Hibernate query will return a list of IDs from the database, and then attempt to load each. If Session.iterate() is used Hibernate goes back to the database to load each object.

Imagine a scenario where we execute a query against the database which returns a hundred IDs and then load each one.

The query takes 20% of the time and the roundtrip loading takes the rest (80%). The database query itself is 75% of the time that the operation takes. The proportion being sped up is thus 60% (75% * 80%).

The expected system speedup is thus:

    1 / ((1 - .6) + .6 / 1000)

    = 1 / (.4 + .006)

    = 2.5 times system speedup

2.4.2.2 Web Page Caching

An observed speed up from caching a web page is 1000 times. Ehcache can retrieve a page from its SimplePageCachingFilter in a few ms.

Because the web page is the end result of a computation, it has a proportion of 100%.

The expected system speedup is thus:

        1 / ((1 - 1) + 1 / 1000)

        = 1 / (0 + .001)

        = 1000 times system speedup

2.4.2.3 Web Page Fragment Caching

Caching the entire page is a big win. Sometimes the liveness requirements vary in different parts of the page. Here the SimplePageFragmentCachingFilter can be used.

Let's say we have a 1000 fold improvement on a page fragment that taking 40% of the page render time.

The expected system speedup is thus:

        1 / ((1 - .4) + .4 / 1000)

        = 1 / (6 + .004)

        = 1.6 times system speedup

2.4.3 Cache EfficiencyContents

In real life cache entrie do not live forever. Some examples that come close are "static" web pages or fragments of same, like page footers, and in the database realm, reference data, such as the currencies in the world.

Factors which affect the efficiency of a cache are:

liveness
how live the data needs to be. The less live the more it can be cached
proportion of data cached
what proportion of the data can fit into the resource limits of the machine. For 32 bit Java systems, there was a hard limit of 2GB of address space. While now relaxed, garbage collection issues make it harder to go a lot large. Various eviction algorithms are used to evict excess entries.
Shape of the usage distribution
If only 300 out of 3000 entries can be cached, but the Pareto distribution applies, it may be that 80% of the time, those 300 will be the ones requested. This drives up the average request lifespan.
Read/Write ratio
The proportion of times data is read compared with how often it is written. Things such as the number of rooms left in a hotel will be written to quite a lot. However the details of a room sold are immutable once created so have a maximum write of 1 with a potentially large number of reads.

Ehcache keeps these statistics for each Cache and each element, so they can be measured directly rather than estimated.

2.4.4 Cluster EfficiencyContents

Also in real life, we generally do not find a single server?

Assume a round robin load balancer where each hit goes to the next server.

The cache has one entry which has a variable lifespan of requests, say caused by a time to live. The following table shows how that lifespan can affect hits and misses.

 Server 1    Server 2   Server 3    Server 4

  M             M           M           M
  H             H           H           H
  H             H           H           H
  H             H           H           H
  H             H           H           H
  ...           ...         ...         ...

The cache hit ratios for the system as a whole are as follows:

Entry
Lifespan  Hit Ratio   Hit Ratio  Hit Ratio   Hit Ratio
in Hits   1 Server    2 Servers  3 Servers   4 Servers

2          1/2           0/2         0/2         0/2
4          3/4           2/4         1/4         0/4
10         9/10          8/10        7/10        6/10
20         19/20         18/20       17/20       16/10
50         49/50         48/50       47/20       46/50

The efficiency of a cluster of standalone caches is generally:

    (Lifespan in requests - Number of Standalone Caches) / Lifespan in requests

Where the lifespan is large relative to the number of standalone caches, cache efficiency is not much affected.

However when the lifespan is short, cache efficiency is dramatically affected.

(To solve this problem, Ehcache supports distributed caching, where an entry put in a local cache is also propagated to other servers in the cluster.)

2.4.5 A cache version of Amdahl's lawContents

From the above we now have:

 1 / ((1 - Proportion Sped Up * effective cache efficiency) +
 (Proportion Sped Up  * effective cache efficiency)/ Speed up)

effective cache efficiency = cache efficiency * cluster efficiency

2.4.6 Web Page exampleContents

Applying this to the earlier web page cache example where we have cache efficiency of 35% and average request lifespan of 10 requests and two servers:

  cache efficiency = .35

  cluster efficiency = .(10 - 1) / 10
                     = .9

  effective cache efficiency = .35 * .9
                             = .315

        1 / ((1 - 1 * .315) + 1 * .315 / 1000)

        = 1 / (.685 + .000315)

        = 1.45 times system speedup

What if, instead the cache efficiency is 70%; a doubling of efficiency. We keep to two servers.

  cache efficiency = .70

  cluster efficiency = .(10 - 1) / 10
                     = .9

  effective cache efficiency = .70 * .9
                             = .63

        1 / ((1 - 1 * .63) + 1 * .63 / 1000)

        = 1 / (.37 + .00063)

        = 2.69 times system speedup

What if, instead the cache efficiency is 90%; a doubling of efficiency. We keep to two servers.

  cache efficiency = .90

  cluster efficiency = .(10 - 1) / 10
                     = .9

  effective cache efficiency = .9 * .9
                             = .81

        1 / ((1 - 1 * .81) + 1 * .81 / 1000)

        = 1 / (.19 + .00081)

        = 5.24 times system speedup

Why is the reduction so dramatic? Because Amdahl's law is most sensitive to the proportion of the system that is sped up.

--- Getting Started ---

3 Getting StartedContents

Firstly, if you have not downloaded Ehcache, you can download it here.

Ehcache can be used directly. It can also be used with the popular Hibernate Object/Relational tool. Finally, it can be used for Java EE Servlet Caching.

This quick guide gets you started on each of these. The rest of the documentation can be explored for a deeper understanding.

3.1 General Purpose CachingContents

3.2 HibernateContents

3.3 Java EE Servlet CachingContents

3.4 RESTful and SOAP Caching with the Cache ServerContents

3.5 JCache style cachingContents

Ehcache contains an early draft implementation of JCache contained in the net.sf.ehcache.jcache package.

See the JSR107 chapter for usage.

3.6 Spring, Cocoon, Acegi and other frameworksContents

Usually, with these, you are using Ehcache without even realising it. The first steps in getting more control over what is happening are:

---- Features ----

4 FeaturesContents

5 %toc|fromDepth=2|toDepth=3Contents

5.1 Fast and Light WeightContents

5.1.1 FastContents

Over the years, various performance tests have shown Ehcache to be one of the fastest Java caches. Ehcache's threading is designed for large, high concurrency systems.

Extensive performance tests in the test suite keep ehcache's performance consistent between releases.

As an example, some guys have created a java cache test tool called cache4j_perfomance_tester.

The results for ehcache-1.1 and ehcache-1.2 follow.

 
  ehcache-1.1

  [java] ---------------------------------------------------------------
  [java] java.version=1.4.2_09
  [java] java.vm.name=Java HotSpot(TM) Client VM
  [java] java.vm.version=1.4.2-54
  [java] java.vm.info=mixed mode
  [java] java.vm.vendor="Apple Computer, Inc."
  [java] os.name=Mac OS X
  [java] os.version=10.4.5
  [java] os.arch=ppc
  [java] ---------------------------------------------------------------
  [java] This test can take about 5-10 minutes. Please wait ...
  [java] ---------------------------------------------------------------
  [java] |GetPutRemoveT |GetPutRemove |Get |
  [java] ---------------------------------------------------------------
  [java] cache4j 0.4 |9240 |9116 |5556 |
  [java] oscache 2.2 |33577 |30803 |8350 |
  [java] Ehcache 1.1 |7697 |6145 |3395 |
  [java] jcs 1.2.7.0 |8966 |9455 |4072 |
  [java] ---------------------------------------------------------------

  ehcache-1.2
  [java] ---------------------------------------------------------------
  [java] java.version=1.4.2_09
  [java] java.vm.name=Java HotSpot(TM) Client VM
  [java] java.vm.version=1.4.2-54
  [java] java.vm.info=mixed mode
  [java] java.vm.vendor="Apple Computer, Inc."
  [java] os.name=Mac OS X
  [java] os.version=10.4.5
  [java] os.arch=ppc
  [java] ---------------------------------------------------------------
  [java] This test can take about 5-10 minutes. Please wait ...
  [java] ---------------------------------------------------------------
  [java] |GetPutRemoveT |GetPutRemove |Get |
  [java] ---------------------------------------------------------------
  [java] cache4j 0.4 |9410 |9053 |5865 |
  [java] oscache 2.2 |28076 |30833 |8031 |
  [java] Ehcache 1.2 |8753 |7072 |3479 |
  [java] jcs 1.2.7.0 |8806 |9522 |4097 |
  [java] ---------------------------------------------------------------

5.1.2 SimpleContents

Many users of Ehcache hardly know they are using it. Sensible defaults require no initial configuration.

The API is very simple and easy to use, making it possible to get up and running in minutes. See the Code Samples for details.

5.1.3 Small foot printContents

Ehcache 1.2 is 110KB making it convenient to package.

5.1.4 Minimal dependenciesContents

The only dependency for core use is the JCACHE API.

5.2 ScalableContents

5.2.1 Provides Memory and Disk stores for scalabilty into gigabytesContents

The largest Ehcache installations use memory and disk stores in the gigabyte range. Ehcache is tuned for these large sizes.

5.2.2 Scalable to hundreds of cachesContents

The largest Ehcache installations use hundreds of caches.

5.2.3 Tuned for high concurrent load on large multi-cpu serversContents

There is a tension between thread safety and performance. Ehcache's threading started off coarse-grained, but has increasingly made use of ideas from Doug Lea to achieve greater performance. Over the years there have been a number of scalability bottlenecks identified and fixed.

5.2.4 Multiple CacheManagers per virtual machineContents

Ehcache 1.2 introduced multiple CacheManagers per virtual machine. This enables completely difference ehcache.xml configurations to be applied.

5.3 FlexibleContents

5.3.1 Supports Object or Serializable cachingContents

As of ehcache-1.2 there is an API for Objects in addition to the one for Serializable. Non-serializable Objects can use all parts of Ehcache except for DiskStore and replication. If an attempt is made to persist or replicate them they are discarded and a WARNING level log message emitted.

The APIs are identical except for the return methods from Element. Two new methods on Element: getObjectValue and getKeyValue are the only API differences between the Serializable and Object APIs. This makes it very easy to start with caching Objects and then change your Objects to Seralizable to participate in the extra features when needed. Also a large number of Java classes are simply not Serializable.

5.3.2 Support cache-wide or Element-based expiry policiesContents

Time to lives and time to idles are settable per cache. In addition, from ehcache-1.2.1, overrides to these can be set per Element.

5.3.3 Provides LRU, LFU and FIFO cache eviction policiesContents

Ehcache 1.2 introduced Less Frequently Used and First In First Out caching eviction policies. These round out the eviction policies.

5.3.4 Provides Memory and Disk storesContents

Ehcache, like most of the cache solutions, provides high performance memory and disk stores.

5.3.5 DistributedContents

Flexible, extensible, high performance distributed caching. The default implementation supports cache discovery via multicast or manual configuration. Updates are delivered either asynchronously or synchronously via custom RMI connections. Additional discovery or delivery schemes can be plugged in by third parties.

See the Distributed Caching documentation for more feature details.

5.3.6 Dynamic, Runtime Configuration of CachesContents

The time-to-live, time-to-idle, maximum in-memory and on-disk capacities can be tuned at runtime simply by mutating the cache's configuration object.

5.4 Standards BasedContents

5.4.1 Full implementation of JSR107 JCACHE APIContents

Ehcache offers the the most complete implementation of the JSR107 JCACHE to date.

Because JCACHE has not yet been released the JCACHE API that Ehcache implements has been released as net.sf.jsr107cache.

Implementers can code to the JCACHE API which will create portability to other caching solutions in the future.

The maintainer of ehcache, Greg Luck, is on the expert committee for JSR107.

5.5 ExtensibleContents

5.5.1 Listeners may be plugged inContents

Ehcache 1.2 provides CacheManagerEventListener and CacheEventListener interfaces. Implementations can be plugged in and configured in ehcache.xml.

5.5.2 Peer Discovery, Replicators and Listeners may be plugged inContents

Distributed caching, introduced in Ehcache 1.2 involves many choices and tradeoffs. The Ehcache team believe that one size will not fit all. Implementers can use built-in mechanisms or write their own. A plugin development guide is included for this purpose.

5.5.3 Cache Extensions may be plugged inContents

Create your own Cache Extensions, which hold a reference to a cache and are bound to its lifecycle.

5.5.4 Cache Loaders may be plugged inContents

Create your own Cache Loaders, which are general purpose asynchronous methods for loading data into caches, or use them in pull-through configuration.

5.5.5 Cache Exception Handlers may be plugged inContents

Create an Exception Handler which is invoked if any Exception occurs on a cache operation.

5.6 Application PersistenceContents

5.6.1 Persistent disk store which stores data between VM restartsContents

With Ehcache 1.1 in 2004, Ehcache was the first open source Java cache to introduce persistent storage of cache data on disk on shutdown. The cached data is then accessible the next time the application runs.

5.6.2 Flush to disk on demandContents

With Ehcache 1.2, the flushing of entries to disk can be executed with a cache.flush() method whenever required, making it easier to use ehcache

5.7 ListenersContents

5.7.1 CacheManager listenersContents

Register Cache Manager listeners through the CacheManagerEventListener interface with the following event methods:

5.7.2 Cache event listenersContents

Register Cache Event Listeners through the CacheEventListener interfaces, which provides a lot of flexibility for post-processing of cache events. The methods are:

5.8 JMX EnabledContents

Ehcache is JMX enabled. You can monitor and manage the following MBeans:

See the net.sf.ehcache.management package.

See http://weblogs.java.net/blog/maxpoon/archive/2007/06/extending_the_n_2.html for an online tutorial.

5.9 Distributed CachingContents

Ehcache 1.2 introduced a full-featured, fine-grained distributed caching mechanism for clusters, supporting multiple replication mechanisms through plugins.

5.9.1 Support for replication via RMI or JGroupsContents

Ehcache 1.6 supports replication via RMI, JGroups, JMS or Terracotta.

5.9.2 Peer DiscoveryContents

Peer discovery may be either manually configured or automatic, using multicast. Multicast is simple, and adds and removes peers automatically. Manual configuration gives fine control and is useful for situations where multicast is blocked.

5.9.3 Reliable DeliveryContents

The built-in delivery mechanism uses RMI with custom sockets over TCP, not UDP.

5.9.4 Synchronous Or Asynchronous ReplicationContents

Replication can be set to synchronous Or asynchronous, per cache.

5.9.5 Copy Or Invalidate ReplicationContents

Replication can be set to copy or invalidate, per cache, as is appropriate.

5.9.6 Transparent ReplicationContents

No programming changes are required to make use of replication. Only configuration in ehcache.xml.

5.9.7 ExtensibleContents

Distributed caching, introduced in Ehcache 1.2 involves many choices and tradeoffs. The Ehcache team believe that one size will not fit all. Implementers can use built-in mechanisms or write their own. A plugin development guide is included for this purpose.

5.9.8 Bootstrapping from PeersContents

Distributed caches enter and leave the cluster at different times. Caches can be configured to bootstrap themselves from the cluster when they are first initialized.

An abstract factory, BootstrapCacheLoaderFactory has been defined along with an interface BootstrapCacheLoader along with an RMI based default implementation.

5.10 Cache ServerContents

Ehcache now comes with a Cache Server, available as a WAR for most web containers, or as a standalone server. The Cache Server has two apis: RESTful resource oriented, and SOAP. Both support clients in any programming language.

5.10.1 RESTful cache serverContents

The Ehcache implementation strictly follows the RESTful resource-oriented architecture style.

Specifically:

5.10.2 SOAP cache serverContents

The Ehcache RESTFul Web Services API exposes the singleton CacheManager, which typically has been configured in ehcache.xml or an IoC container. Multiple CacheManagers are not supported.

The API definition is as follows:

5.10.3 comes as a WAR or as a complete serverContents

The standalone server comes with its own embedded Glassfish web container.

It also comes packaged as a WAR for deployment to any Servlet 2.5 web container. Glassfish V2/3, Tomcat 6 and Jetty 6 have been tested.

5.11 Java EE and Applied CachingContents

High quality implementations for common caching scenarios and patterns.

5.11.1 Blocking Cache to avoid duplicate processing for concurrent operationsContents

A cache which blocks subsequent threads until the first read thread populates a cache entry.

5.11.2 SelfPopulating Cache for pull through caching of expensive operationsContents

SelfPopulatingCache - a read-through cache. A cache that populates elements as they are requested without requiring the caller to know how the entries are populated. It also enables refreshes of cache entries without blocking reads on the same entries.

5.11.3 Java EE Gzipping Servlet FilterContents

5.11.4 Cacheable CommandsContents

This is the trusty old command pattern with a twist: asynchronous behaviour, fault tolerance and caching. Creates a command, caches it and then attempts to execute it.

5.11.5 Works with HibernateContents

Tested with Hibernate2.1.8 and Hibernate3.1.3, which can utilise all of the new features except for Object API and multiple session factories each using a different Ehcache CacheManager.

A new net.sf.ehcache.hibernate.EhCacheProvider makes those additional features available to Hibernate-3.1.3. A version of the new provider should make it into the Hibernate3.2 release.

5.11.6 Works with Google App EngineContents

Ehcache-1.6 is compatible with Google App Engine.

See the Google App Engine HowTo.

5.11.7 Transactional support through JTAContents

Ehcache-2.0 has support for JTA, making it a fully XA compliant resource participating in the transaction, two-phase commit and recovery.

See the complete JTA documentation.

5.12 High QualityContents

5.12.1 High Test CoverageContents

The Ehcache team believe that the first and most important quality measure is a well designed and comprehensive test suite.

Ehcache has a relatively high 86% test coverage of source code. This has edged higher over time. Clover enforces the test coverage. Most of the missing 14% is logging and exception paths.

5.12.2 Automated Load, Limit and Performance System TestsContents

The Ehcache JUnit test suite contains some long-running system tests which place high load on different Ehcache subsystems to the point of failure and then are back off to just below that point. The same is done with limits such as the amount of Elements that can fit in a given heap size. The same is also done with performance testing of each subsystem and the whole together. The same is also done with network tests for cache replication.

The tests serve a number of purposes:

5.12.3 Specific Concurrency TestingContents

Ehcache also has concurrency testing, which typically uses 50 concurrent threads hammering a piece of code. The test suites are also run on multi-core or multi-cpu machines so that concurrency is real rather than simulated. Additionally, every concurrency related issue that has ever been anticipated or resulted in a bug report has a unit test which prevents the condition from recurring. There are no reported issues that have not been reproduced in a unit test.

Concurrency unit tests are somewhat difficult to write, and are often overlooked. The team considers these tests a major factor in ehcache's quality.

5.12.4 Production testedContents

Ehcache came about in the first place because of production issues with another open source cache.

Final release versions of Ehcache have been production tested on a very busy e-commerce site, supporting thousands of concurrent users, gigabyte size caches on large multi-cpu machines. It has been the experience of the team that most threading issues do not surface until this type of load has been applied. Once an issue has been identified and investigated a concurrency unit test can then be crafted.

5.12.5 Fully documentedContents

A core belief held by the project team is that a project needs good documentation to be useful.

In ehcache, this is manifested by:

5.12.6 Trusted by Popular FrameworksContents

Ehcache is used extensively. See the Who is Using? page, or browse Google.

5.12.7 Conservative Commit policyContents

Projects like Linux maintain their quality through a restricted change process, whereby changes are submitted as patches, then reviewed by the maintainer and included, or modified. Ehcache follows the same process.

5.12.8 Full public information on the history of every bugContents

Through the SourceForge project bug tracker, the full history of all bugs are shown, including current status. We take this for granted in an open source project, as this is typically a feature that all open source projects have, but this transparency makes it possible to gauge the quality and riskiness of a library, something not usually possible in commercial products.

5.12.9 Responsiveness to serious bugsContents

The Ehcache team is serious about quality. If one user is having a problem, it probably means others are too, or will have. The Ehcache team use Ehcache themselves in production. Every effort will be made to provide fixes for serious production problems as soon as possible. These will be committed to trunk. From there an affected user can apply the fix to their own branch.

5.13 Open Source LicensingContents

5.13.1 Apache 2.0 licenseContents

Ehcache's original Apache1.1 copyright and licensing was reviewed and approved by the Apache Software Foundation, making Ehcache suitable for use in Apache projects. ehcache-1.2 is released under the updated Apache 2.0 license.

The Apache license is also friendly one, making it safe and easy to include Ehcache in other open source projects or commercial products.

--- Key Concepts ---

6 Key Ehcache ConceptsContents

6.1 Key Ehcache ClassesContents

javadoc/net/sf/ehcache/package

Top Level Package Diagram

Ehcache consists of a CacheManager, which manages caches. Caches contain elements, which are essentially name value pairs. Caches are physically implemented either in-memory, or on disk.

6.1.1 CacheManagerContents

javadoc/net/sf/ehcache/CacheManager

CacheManager Class Diagram

The CacheManager comprises Caches which in turn comprise Elements.

Creation of, access to and removal of caches is controlled by the CacheManager.

6.1.1.1 CacheManager Creation Modes

CacheManager supports two creation modes: singleton and instance.

6.1.1.1.1 Singleton Mode

Ehcache-1.1 supported only one CacheManager instance which was a singleton. CacheManager can still be used in this way using the static factory methods.

6.1.1.1.2 Instance Mode

From ehcache-1.2, CacheManager has constructors which mirror the various static create methods. This enables multiple CacheManagers to be created and used concurrently. Each CacheManager requires its own configuration.

If the Caches under management use only the MemoryStore, there are no special considerations. If Caches use the DiskStore, the diskStore path specified in each CacheManager configuration should be unique. When a new CacheManager is created, a check is made that there are no other CacheManagers using the same diskStore path. If there are, a CacheException is thrown. If a CacheManager is part of a cluster, there will also be listener ports which must be unique.

6.1.1.1.3 Mixed Singleton and Instance Mode

If an application creates instances of CacheManager using a constructor, and also calls a static create method, there will exist a singleton instance of CacheManager which will be returned each time the create method is called together with any other instances created via constructor. The two types will coexist peacefully.

6.1.2 EhcacheContents

javadoc/net/sf/ehcache/Ehcache

Ehcache Interface Diagram

All caches implement the Ehcache interface. A cache has a name and attributes. Each cache contains Elements.

A Cache in Ehcache is analogous to a cache region in other caching systems.

Cache elements are stored in the MemoryStore. Optionally they also overflow to a DiskStore.

6.1.3 ElementContents

javadoc/net/sf/ehcache/Element

Element Class Diagram

An element is an atomic entry in a cache. It has a key, a value and a record of accesses. Elements are put into and removed from caches. They can also expire and be removed by the Cache, depending on the Cache settings.

As of ehcache-1.2 there is an API for Objects in addition to the one for Serializable. Non-serializable Objects can use all parts of Ehcache except for DiskStore and replication. If an attempt is made to persist or replicate them they are discarded without error and with a DEBUG level log message.

The APIs are identical except for the return methods from Element. Two new methods on Element: getObjectValue and getKeyValue are the only API differences between the Serializable and Object APIs. This makes it very easy to start with caching Objects and then change your Objects to Seralizable to participate in the extra features when needed. Also a large number of Java classes are simply not Serializable.

6.2 Cache Usage PatternsContents

Caches can be used in different ways. Each of these ways follows a cache usage pattern. Ehcache supports the following:

6.2.1 Direct ManipulationContents

Here, to put something in the cache you do cache.put(Element element) and to get something from the cache you do cache.get(Object key).

You are aware you are using a cache and you are doing so consciously.

6.2.2 Self PopulatingContents

Here, you just do gets to the cache using cache.get(Object key). The cache itself knows how to populate an entry.

See the SelfPopulatingCache for more on this pattern.

--- Architecture ---

7 ArchitectureContents

This diagram shows the architecture of Ehcache. It is current as of Ehcache-1.6.2.

images/layered_architecture

--- Cache Configuration ---

8 Cache ConfigurationContents

Caches can be configured in Ehcache either declaratively, in xml, or by creating them programmatically and specifying their parameters in the constructor.

While both approaches are fully supported it is generally a good idea to separate the cache configuration from runtime use. There are also these benefits:

Certain aspects of cache configuration can also be modified dynamically at runtime.

This chapter covers XML declarative configuration. See the Code samples for programmatic and dynamic configuration.

Ehcache is redistributed by lots of projects. They may or may not provide a sample Ehcache XML configuration file. If one is not provided, download Ehcache from http://ehcache.org. It, and the ehcache.xsd is provided in the distribution.

8.1 ehcache.xsdContents

Ehcache configuration files must be comply with the Ehcache XML schema, ehcache.xsd, reproduced below.

It can also be downloaded from http://ehcache.org/ehcache.xsd.

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
    version="1.7">

  <xs:element name="ehcache" >
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="1" ref="diskStore"/>
        <xs:element minOccurs="0" maxOccurs="1"
              ref="cacheManagerEventListenerFactory"/>
        <xs:element minOccurs="0" maxOccurs="unbounded"
              ref="cacheManagerPeerProviderFactory"/>
        <xs:element minOccurs="0" maxOccurs="unbounded"
              ref="cacheManagerPeerListenerFactory"/>
        <xs:element minOccurs="0" maxOccurs="1"
              ref="terracottaConfig"/>
        <xs:element ref="defaultCache"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="cache"/>
      </xs:sequence>
      <xs:attribute name="name" use="optional"/>
      <xs:attribute name="updateCheck" use="optional" type="xs:boolean" default="true"/>
      <xs:attribute name="monitoring" use="optional" type="monitoringType"
      default="autodetect"/>
    </xs:complexType>
  </xs:element>   
  <xs:element name="diskStore">
    <xs:complexType>
      <xs:attribute name="path" use="optional" />
    </xs:complexType>
  </xs:element>
  <xs:element name="cacheManagerEventListenerFactory">
    <xs:complexType>
      <xs:attribute name="class" use="required"/>
      <xs:attribute name="properties" use="optional"/>
      <xs:attribute name="propertySeparator" use="optional"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="cacheManagerPeerProviderFactory">
    <xs:complexType>
      <xs:attribute name="class" use="required"/>
      <xs:attribute name="properties" use="optional"/>
      <xs:attribute name="propertySeparator" use="optional"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="cacheManagerPeerListenerFactory">
    <xs:complexType>
      <xs:attribute name="class" use="required"/>
      <xs:attribute name="properties" use="optional"/>
      <xs:attribute name="propertySeparator" use="optional"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="terracottaConfig">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="tc-config" minOccurs="0" maxOccurs="1">
          <xs:complexType>
            <xs:sequence>
              <xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip" />
            </xs:sequence>
          </xs:complexType>    
        </xs:element>
      </xs:sequence>
      <xs:attribute name="url" use="optional" default="localhost:9510"/>
      <xs:attribute name="registerStatsMBean" type="xs:boolean" use="optional"/>
    </xs:complexType>
  </xs:element>  
  <!-- add clone support for addition of cacheExceptionHandler. Important! -->
  <xs:element name="defaultCache">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheEventListenerFactory"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheExtensionFactory"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheLoaderFactory"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="bootstrapCacheLoaderFactory"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="cacheExceptionHandlerFactory"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="terracotta"/>
      </xs:sequence>
      <xs:attribute name="diskExpiryThreadIntervalSeconds" use="optional" type="xs:integer"/>
      <xs:attribute name="diskSpoolBufferSizeMB" use="optional" type="xs:integer"/>
      <xs:attribute name="diskPersistent" use="optional" type="xs:boolean"/>
      <xs:attribute name="diskAccessStripes" type="xs:integer" use="optional" default="1"/>
      <xs:attribute name="eternal" use="required" type="xs:boolean"/>
      <xs:attribute name="maxElementsInMemory" use="required" type="xs:integer"/>
      <xs:attribute name="clearOnFlush" use="optional" type="xs:boolean"/>
      <xs:attribute name="memoryStoreEvictionPolicy" use="optional" type="xs:string"/>
      <xs:attribute name="overflowToDisk" use="required" type="xs:boolean"/>
      <xs:attribute name="timeToIdleSeconds" use="optional" type="xs:integer"/>
      <xs:attribute name="timeToLiveSeconds" use="optional" type="xs:integer"/>
      <xs:attribute name="maxElementsOnDisk" use="optional" type="xs:integer"/>
      <xs:attribute name="statistics" type="xs:boolean" use="optional" default="true"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="cache">
    <xs:complexType>
      <xs:sequence >
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheEventListenerFactory"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheExtensionFactory"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheLoaderFactory"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="bootstrapCacheLoaderFactory"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="cacheExceptionHandlerFactory"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="terracotta"/>
      </xs:sequence>
      <xs:attribute name="diskExpiryThreadIntervalSeconds" use="optional"
      type="xs:integer"/>
      <xs:attribute name="diskSpoolBufferSizeMB" use="optional" type="xs:integer"/>
      <xs:attribute name="diskPersistent" use="optional" type="xs:boolean"/>
      <xs:attribute name="diskAccessStripes" type="xs:integer" use="optional" default="1"/>
      <xs:attribute name="eternal" use="required" type="xs:boolean"/>
      <xs:attribute name="maxElementsInMemory" use="required" type="xs:integer"/>
      <xs:attribute name="memoryStoreEvictionPolicy" use="optional" type="xs:string"/>
      <xs:attribute name="clearOnFlush" use="optional" type="xs:boolean"/>
      <xs:attribute name="name" use="required" type="xs:string"/>
      <xs:attribute name="overflowToDisk" use="required" type="xs:boolean"/>
      <xs:attribute name="timeToIdleSeconds" use="optional" type="xs:integer"/>
      <xs:attribute name="timeToLiveSeconds" use="optional" type="xs:integer"/>
      <xs:attribute name="maxElementsOnDisk" use="optional" type="xs:integer"/>
      <xs:attribute name="statistics" type="xs:boolean" use="optional" default="true"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="cacheEventListenerFactory">
    <xs:complexType>
      <xs:attribute name="class" use="required"/>
      <xs:attribute name="properties" use="optional"/>
      <xs:attribute name="propertySeparator" use="optional"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="bootstrapCacheLoaderFactory">
    <xs:complexType>
      <xs:attribute name="class" use="required"/>
      <xs:attribute name="properties" use="optional"/>
      <xs:attribute name="propertySeparator" use="optional"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="cacheExtensionFactory">
    <xs:complexType>
      <xs:attribute name="class" use="required"/>
      <xs:attribute name="properties" use="optional"/>
      <xs:attribute name="propertySeparator" use="optional"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="cacheExceptionHandlerFactory">
    <xs:complexType>
      <xs:attribute name="class" use="required"/>
      <xs:attribute name="properties" use="optional"/>
      <xs:attribute name="propertySeparator" use="optional"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="cacheLoaderFactory">
    <xs:complexType>
      <xs:attribute name="class" use="required"/>
      <xs:attribute name="properties" use="optional"/>
      <xs:attribute name="propertySeparator" use="optional"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="terracotta">
    <xs:complexType>
      <xs:attribute name="clustered" use="optional" type="xs:boolean" default="true"/>
      <xs:attribute name="valueMode" use="optional"
        type="terracottaCacheValueType" default="serialization"/>
      <xs:attribute name="coherentReads" use="optional" type="xs:boolean" default="true"/>
      <xs:attribute name="localKeyCache" use="optional" type="xs:boolean" default="false"/>
      <xs:attribute name="localKeyCacheSize" use="optional" type="xs:positiveInteger" default="10000"/>
      <xs:attribute name="orphanEviction" use="optional" type="xs:boolean" default="true"/>
      <xs:attribute name="orphanEvictionPeriod" use="optional" type="xs:positiveInteger" default="4"/>
    </xs:complexType>
  </xs:element>
  <xs:simpleType name="monitoringType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="autodetect" />
      <xs:enumeration value="on" />
      <xs:enumeration value="off" />
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="terracottaCacheValueType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="serialization" />
      <xs:enumeration value="identity" />
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

8.2 ehcache-failsafe.xmlContents

If the CacheManager default constructor or factory method is called, Ehcache looks for a file called ehcache.xml in the top level of the classpath. Failing that it looks for ehcache-failsafe.xml in the classpath. ehcache-failsafe.xml is packaged in the Ehcache jar and should always be found.

ehcache-failsafe.xml provides an extremely simple default configuration to enable users to get started before they create their own ehcache.xml.

If it used Ehcache will emit a warning, reminding the user to set up a proper configuration.

The meaning of the elements and attributes are explained in the section on ehcache.xml.

<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="true"
            maxElementsOnDisk="10000000"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
            />
</ehcache>

8.3 ehcache.xml and other configuration filesContents

Prior to ehcache-1.6, Ehcache only supported ASCII ehcache.xml configuration files. Since ehcache-1.6, UTF8 is supported, so that configuration can use Unicode. As UTF8 is backwardly compatible with ASCII, no conversion is necessary.

If the CacheManager default constructor or factory method is called, Ehcache looks for a file called ehcache.xml in the top level of the classpath.

The non-default creation methods allow a configuration file to be specified which can be called anything.

One XML configuration is required for each CacheManager that is created. It is an error to use the same configuration, because things like directory paths and listener ports will conflict. Ehcache will attempt to resolve conflicts and will emit a warning reminding the user to configure a separate configuration for multiple CacheManagers with conflicting settings.

The sample ehcache.xml, which is included in the Ehcache distribution is reproduced below. The sample contains full commentary required to configure each element. Further information can be found in specific chapters in the Guide.

It can also be downloaded from http://ehcache.org/ehcache.xml.

<?xml version="1.0" encoding="UTF-8"?>

<!--
CacheManager Configuration
==========================
An ehcache.xml corresponds to a single CacheManager.

See instructions below or the ehcache schema (ehcache.xsd) on how to configure.

System property tokens can be specified in this file which are replaced when the
configuration is loaded. For example multicastGroupPort=${multicastGroupPort}
can be replaced with the System property either from an environment variable or
a system property specified with a command line switch such as
-DmulticastGroupPort=4446.

The attributes of <ehcache> are:
* name - an optional name for the CacheManager.  The name is optional and primarily used
for documentation or to distinguish Terracotta clustered cache state.  With Terracotta
clustered caches, a combination of CacheManager name and cache name uniquely identify a
particular cache store in the Terracotta clustered memory.
* updateCheck - an optional boolean flag specifying whether this CacheManager should check
for new versions of Ehcache over the Internet.  If not specified, updateCheck="true".
* dynamicConfig - an optional boolean flag specifying whether this CacheManager should
support dynamic configuration changes to its attached caches.
* monitoring - an optional setting that determines whether the CacheManager should
automatically register the SampledCacheMBean with the system MBean server.

Currently, this monitoring is only useful when using Terracotta clustering and using the
Terracotta Developer Console. With the "autodetect" value, the presence of Terracotta
clustering will be detected and monitoring, via the Developer Console, will be enabled.
Other allowed values are "on" and "off".  The default is "autodetect". This setting does
not perform any function when used with JMX monitors.
-->
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="ehcache.xsd"
             updateCheck="true" monitoring="autodetect">

<!--
DiskStore configuration
=======================

The diskStore element is optional. To turn off disk store path creation, comment out
the diskStore element below.

Configure it if you have overflowToDisk or diskPersistent enabled for any cache.

If it is not configured, and a cache is created which requires a disk store, a warning
will be issued and java.io.tmpdir will automatically be used.

diskStore has only one attribute - "path". It is the path to the directory where
.data and .index files will be created.

If the path is one of the following Java System Property it is replaced by its value
in the running VM. For backward compatibility these should be specified without being
enclosed in the ${token} replacement syntax.

The following properties are translated:
* user.home - User's home directory
* user.dir - User's current working directory
* java.io.tmpdir - Default temp file path
* ehcache.disk.store.dir - A system property you would normally specify on the command
 line e.g. java -Dehcache.disk.store.dir=/u01/myapp/diskdir ...

Subdirectories can be specified below the property e.g. java.io.tmpdir/one

-->
<diskStore path="java.io.tmpdir"/>

<!--
CacheManagerEventListener
=========================
Specifies a CacheManagerEventListenerFactory which is notified when Caches are added
or removed from the CacheManager.

The attributes of CacheManagerEventListenerFactory are:
* class - a fully qualified factory class name
* properties - comma separated properties having meaning only to the factory.

Sets the fully qualified class name to be registered as the CacheManager event listener.

The events include:
* adding a Cache
* removing a Cache

Callbacks to listener methods are synchronous and unsynchronized. It is the
responsibility of the implementer to safely handle the potential performance and
thread safety issues depending on what their listener is doing.

If no class is specified, no listener is created. There is no default.
-->
<cacheManagerEventListenerFactory class="" properties=""/>


<!--
CacheManagerPeerProvider
========================
(For distributed operation)

Specifies a CacheManagerPeerProviderFactory which will be used to create a
CacheManagerPeerProvider, which discovers other CacheManagers in the cluster.

One or more providers can be configured. The first one in the ehcache.xml is the
default, which is used for replication and bootstrapping.

The attributes of cacheManagerPeerProviderFactory are:
* class - a fully qualified factory class name
* properties - comma separated properties having meaning only to the factory.

Providers are available for RMI, JGroups and JMS as shown following.

RMICacheManagerPeerProvider
+++++++++++++++++++++++++++

Ehcache comes with a built-in RMI-based distribution system with two means of discovery
of CacheManager peers participating in the cluster:

* automatic, using a multicast group. This one automatically discovers peers and detects
  changes such as peers entering and leaving the group
* manual, using manual rmiURL configuration. A hardcoded list of peers is provided at
  configuration time.

Configuring Automatic Discovery:
Automatic discovery is configured as per the following example:
<cacheManagerPeerProviderFactory
                    class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
                    properties="hostName=fully_qualified_hostname_or_ip,
                                peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
                                multicastGroupPort=4446, timeToLive=32"/>

Valid properties are:
* peerDiscovery (mandatory) - specify "automatic"
* multicastGroupAddress (mandatory) - specify a valid multicast group address
* multicastGroupPort (mandatory) - specify a dedicated port for the multicast heartbeat
  traffic
* timeToLive - specify a value between 0 and 255 which determines how far the packets
  will propagate.

  By convention, the restrictions are:
  0   - the same host
  1   - the same subnet
  32  - the same site
  64  - the same region
  128 - the same continent
  255 - unrestricted

 * hostName - the hostname or IP of the interface to be used for sending and receiving
   multicast packets (relevant to mulithomed hosts only)

Configuring Manual Discovery:
Manual discovery requires a unique configuration per host. It is contains a list of
rmiURLs for the peers, other than itself. So, if we have server1, server2 and server3
the configuration will be:

In server1's configuration:
<cacheManagerPeerProviderFactory class=
                      "net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
                      properties="peerDiscovery=manual,
                      rmiUrls=//server2:40000/sampleCache1|//server3:40000/sampleCache1
                      | //server2:40000/sampleCache2|//server3:40000/sampleCache2"
                      propertySeparator="," />

In server2's configuration:
<cacheManagerPeerProviderFactory class=
                      "net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
                      properties="peerDiscovery=manual,
                      rmiUrls=//server1:40000/sampleCache1|//server3:40000/sampleCache1
                      | //server1:40000/sampleCache2|//server3:40000/sampleCache2"
                      propertySeparator="," />

In server3's configuration:
<cacheManagerPeerProviderFactory class=
                      "net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
                      properties="peerDiscovery=manual,
                      rmiUrls=//server1:40000/sampleCache1|//server2:40000/sampleCache1
                      | //server1:40000/sampleCache2|//server2:40000/sampleCache2"
                      propertySeparator="," />


Valid properties are:
* peerDiscovery (mandatory) - specify "manual"
* rmiUrls (mandatory) - specify a pipe separated list of rmiUrls, in the form
                        //hostname:port
* hostname (optional) - the hostname is the hostname of the remote CacheManager peer.
  The port is the listening port of the RMICacheManagerPeerListener of the remote
  CacheManager peer.

JGroupsCacheManagerPeerProvider
+++++++++++++++++++++++++++++++
<cacheManagerPeerProviderFactory
 class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"
 properties="connect=UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_ttl=32;
 mcast_send_buf_size=150000;mcast_recv_buf_size=80000):
 PING(timeout=2000;num_initial_members=6):
 MERGE2(min_interval=5000;max_interval=10000):
 FD_SOCK:VERIFY_SUSPECT(timeout=1500):
 pbcast.NAKACK(gc_lag=10;retransmit_timeout=3000):
 UNICAST(timeout=5000):
 pbcast.STABLE(desired_avg_gossip=20000):
 FRAG:
 pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;print_local_addr=false)"
 propertySeparator="::"
        />
 The only property necessary is the connect String used by jgroups to configure itself.
 Refer to the JGroups documentation for explanation of all the protocols. The example above
 uses UDP multicast. If the connect property is not specified the default JGroups connection
 will be used.


JMSCacheManagerPeerProviderFactory
++++++++++++++++++++++++++++++++++
<cacheManagerPeerProviderFactory
        class="net.sf.ehcache.distribution.jms.JMSCacheManagerPeerProviderFactory"
        properties="..."
        propertySeparator=","
        />

The JMS PeerProviderFactory uses JNDI to maintain message queue independence. Refer to the
    manual for full configuration examples using ActiveMQ and Open Message Queue.

Valid properties are:
* initialContextFactoryName (mandatory) - the name of the factory used to create the
    message queue initial context.
* providerURL (mandatory) - the JNDI configuration information for the service provider
    to use.
* topicConnectionFactoryBindingName (mandatory) - the JNDI binding name for the
    TopicConnectionFactory
* topicBindingName (mandatory) - the JNDI binding name for the topic name
* getQueueBindingName (mandatory only if using jmsCacheLoader) - the JNDI binding name for
    the queue name
* securityPrincipalName - the JNDI java.naming.security.principal
* securityCredentials - the JNDI java.naming.security.credentials
* urlPkgPrefixes - the JNDI java.naming.factory.url.pkgs
* userName - the user name to use when creating the TopicConnection to the Message Queue
* password - the password to use when creating the TopicConnection to the Message Queue
* acknowledgementMode - the JMS Acknowledgement mode for both publisher and subscriber.
    The available choices are AUTO_ACKNOWLEDGE, DUPS_OK_ACKNOWLEDGE and SESSION_TRANSACTED.
      The default is AUTO_ACKNOWLEDGE.
-->
<cacheManagerPeerProviderFactory
        class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
        properties="peerDiscovery=automatic,
                    multicastGroupAddress=230.0.0.1,
                    multicastGroupPort=4446, timeToLive=1"
        propertySeparator=","
        />


<!--
CacheManagerPeerListener
========================
(Enable for distributed operation)

Specifies a CacheManagerPeerListenerFactory which will be used to create a
CacheManagerPeerListener, which listens for messages from cache replicators participating
 in the cluster.

The attributes of cacheManagerPeerListenerFactory are:
class - a fully qualified factory class name
properties - comma separated properties having meaning only to the factory.

Ehcache comes with a built-in RMI-based distribution system. The listener component is
RMICacheManagerPeerListener which is configured using
RMICacheManagerPeerListenerFactory. It is configured as per the following example:

<cacheManagerPeerListenerFactory
    class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
    properties="hostName=fully_qualified_hostname_or_ip,
                port=40001,
                remoteObjectPort=40002,
                socketTimeoutMillis=120000"
                propertySeparator="," />

All properties are optional. They are:
* hostName - the hostName of the host the listener is running on. Specify
  where the host is multihomed and you want to control the interface over which cluster
  messages are received. Defaults to the host name of the default interface if not
  specified.
* port - the port the RMI Registry listener listens on. This defaults to a free port
  if not specified.
* remoteObjectPort - the port number on which the remote objects bound in the registry
  receive calls. This defaults to a free port if not specified.
* socketTimeoutMillis - the number of ms client sockets will stay open when sending
  messages to the listener. This should be long enough for the slowest message.
  If not specified it defaults to 120000ms.

-->
<cacheManagerPeerListenerFactory
        class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/>

<!--
TerracottaConfig
========================
(Enable for Terracotta clustered operation)

Note: You need to install and run one or more Terracotta servers to use Terracotta
clustering. See http://www.terracotta.org/web/display/orgsite/Download.

Specifies a TerracottaConfig which will be used to configure the Terracotta
runtime for this CacheManager.

Configuration can be specified in two main ways: by reference to a source of
configuration or by use of an embedded Terracotta configuration file.

To specify a reference to a source (or sources) of configuration, use the url
attribute.  The url attribute must contain a comma-separated list of:
* path to Terracotta configuration file (usually named tc-config.xml)
* URL to Terracotta configuration file
* <server host>:<port> of running Terracotta Server instance

Simplest example for pointing to a Terracotta server on this machine:
<terracottaConfig url="localhost:9510"/>

Example using a path to Terracotta configuration file:
<terracottaConfig url="/app/config/tc-config.xml"/>

Example using a URL to a Terracotta configuration file:
<terracottaConfig url="http://internal/ehcache/app/tc-config.xml"/>

Example using multiple Terracotta server instance URLs (for fault tolerance):
<terracottaConfig url="host1:9510,host2:9510,host3:9510"/>

To embed a Terracotta configuration file within the ehcache configuration, simply
place a normal Terracotta XML config within the <terracottaConfig> element.

Example:
<terracottaConfig>
    <tc-config>
        <servers>
            <server host="server1" name="s1"/>
            <server host="server2" name="s2"/>
        </servers>
        <clients>
            <logs>app/logs-%i</logs>
        </clients>
    </tc-config>
</terracottaConfig>

For more information on the Terracotta configuration, see the Terracotta documentation.
-->

<!--
Cache configuration
===================

The following attributes are required.

name:
Sets the name of the cache. This is used to identify the cache. It must be unique.

maxElementsInMemory:
Sets the maximum number of objects that will be created in memory.
0 indicates no in-memory limit.

maxElementsOnDisk:
Sets the maximum number of objects that will be maintained in the DiskStore
The default value is zero, meaning unlimited.

eternal:
Sets whether elements are eternal. If eternal,  timeouts are ignored and the
element is never expired.

overflowToDisk:
Sets whether elements can overflow to disk when the memory store
has reached the maxInMemory limit.

The following attributes and elements are optional.

timeToIdleSeconds:
Sets the time to idle for an element before it expires.
i.e. The maximum amount of time between accesses before an element expires
Is only used if the element is not eternal.
Optional attribute. A value of 0 means that an Element can idle for infinity.
The default value is 0.

timeToLiveSeconds:
Sets the time to live for an element before it expires.
i.e. The maximum time between creation time and when an element expires.
Is only used if the element is not eternal.
Optional attribute. A value of 0 means that and Element can live for infinity.
The default value is 0.

diskPersistent:
Whether the disk store persists between restarts of the Virtual Machine.
The default value is false.

diskExpiryThreadIntervalSeconds:
The number of seconds between runs of the disk expiry thread. The default value
is 120 seconds.

diskSpoolBufferSizeMB:
This is the size to allocate the DiskStore for a spool buffer. Writes are made
to this area and then asynchronously written to disk. The default size is 30MB.
Each spool buffer is used only by its cache. If you get OutOfMemory errors consider
lowering this value. To improve DiskStore performance consider increasing it. Trace level
logging in the DiskStore will show if put back ups are occurring.

diskAccessStripes:
By default one RandomAccessFile object is created to read/write to and from the disk store.
By specifying a larger value here, multiple threads can read/write from the store concurrently
(assuming that the disk controller/driver can correctly optimize the resultant access to the disk).

clearOnFlush:
whether the MemoryStore should be cleared when flush() is called on the cache.
By default, this is true i.e. the MemoryStore is cleared.

memoryStoreEvictionPolicy:
Policy would be enforced upon reaching the maxElementsInMemory limit. Default
policy is Least Recently Used (specified as LRU). Other policies available -
First In First Out (specified as FIFO) and Less Frequently Used
(specified as LFU)

statistics:
Whether the Cache has statistics enabled upon creation.  The default is to
enable statistics on cache creation.

Cache elements can also contain sub elements which take the same format of a factory class
and properties. Defined sub-elements are:

* cacheEventListenerFactory - Enables registration of listeners for cache events, such as
  put, remove, update, and expire.

* bootstrapCacheLoaderFactory - Specifies a BootstrapCacheLoader, which is called by a
  cache on initialisation to prepopulate itself.

* cacheExtensionFactory - Specifies a CacheExtension, a generic mechansim to tie a class
  which holds a reference to a cache to the cache lifecycle.

* cacheExceptionHandlerFactory - Specifies a CacheExceptionHandler, which is called when
  cache exceptions occur.

* cacheLoaderFactory - Specifies a CacheLoader, which can be used both asynchronously and
  synchronously to load objects into a cache. More than one cacheLoaderFactory element
  can be added, in which case the loaders form a chain which are executed in order. If a
  loader returns null, the next in chain is called.


RMI Cache Replication
+++++++++++++++++++++

Each cache that will be distributed needs to set a cache event listener which replicates
messages to the other CacheManager peers. For the built-in RMI implementation this is done
by adding a cacheEventListenerFactory element of type RMICacheReplicatorFactory to each
distributed cache's configuration as per the following example:

<cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
     properties="replicateAsynchronously=true,
     replicatePuts=true,
     replicatePutsViaCopy=false,
     replicateUpdates=true,
     replicateUpdatesViaCopy=true,
     replicateRemovals=true
     asynchronousReplicationIntervalMillis=<number of milliseconds"
     propertySeparator="," />

The RMICacheReplicatorFactory recognises the following properties:

* replicatePuts=true|false - whether new elements placed in a cache are
  replicated to others. Defaults to true.

* replicatePutsViaCopy=true|false - whether the new elements are
  copied to other caches (true), or whether a remove message is sent. Defaults to true.

* replicateUpdates=true|false - whether new elements which override an
  element already existing with the same key are replicated. Defaults to true.

* replicateRemovals=true - whether element removals are replicated. Defaults to true.

* replicateAsynchronously=true | false - whether replications are
  asynchronous (true) or synchronous (false). Defaults to true.

* replicateUpdatesViaCopy=true | false - whether the new elements are
  copied to other caches (true), or whether a remove message is sent. Defaults to true.

* asynchronousReplicationIntervalMillis=<number of milliseconds> - The asynchronous
  replicator runs at a set interval of milliseconds. The default is 1000. The minimum
  is 10. This property is only applicable if replicateAsynchronously=true


JGroups Replication
+++++++++++++++++++

For the Jgroups replication this is done with:
<cacheEventListenerFactory
    class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
                properties="replicateAsynchronously=true, replicatePuts=true,
                replicateUpdates=true, replicateUpdatesViaCopy=false,
                replicateRemovals=true,asynchronousReplicationIntervalMillis=1000"/>
This listener supports the same properties as the RMICacheReplicationFactory.


JMS Replication
+++++++++++++++

For JMS-based replication this is done with:
<cacheEventListenerFactory
      class="net.sf.ehcache.distribution.jms.JMSCacheReplicatorFactory"
      properties="replicateAsynchronously=true,
                   replicatePuts=true,
                   replicateUpdates=true,
                   replicateUpdatesViaCopy=true,
                   replicateRemovals=true,
                   asynchronousReplicationIntervalMillis=1000"
       propertySeparator=","/>

This listener supports the same properties as the RMICacheReplicationFactory.

Cluster Bootstrapping
+++++++++++++++++++++

Bootstrapping a cluster may use a different mechanism to replication. e.g you can mix
JMS replication with bootstrap via RMI - just make sure you have the
cacheManagerPeerProviderFactory and cacheManagerPeerListenerFactory configured.

There are two bootstrapping mechanisms: RMI and JGroups.

RMI Bootstrap

The RMIBootstrapCacheLoader bootstraps caches in clusters where RMICacheReplicators are
used. It is configured as per the following example:

<bootstrapCacheLoaderFactory
    class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
    properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"
    propertySeparator="," />

The RMIBootstrapCacheLoaderFactory recognises the following optional properties:

* bootstrapAsynchronously=true|false - whether the bootstrap happens in the background
  after the cache has started. If false, bootstrapping must complete before the cache is
  made available. The default value is true.

* maximumChunkSizeBytes=<integer> - Caches can potentially be very large, larger than the
  memory limits of the VM. This property allows the bootstraper to fetched elements in
  chunks. The default chunk size is 5000000 (5MB).

JGroups Bootstrap

Here is an example of bootstrap configuration using JGroups boostrap:

<bootstrapCacheLoaderFactory
    class="net.sf.ehcache.distribution.jgroups.JGroupsBootstrapCacheLoaderFactory"
                                properties="bootstrapAsynchronously=true"/>

The configuration properties are the same as for RMI above. Note that JGroups bootstrap
only supports asynchronous bootstrap mode.


Cache Exception Handling

By default, most cache operations will propagate a runtime CacheException on failure. An
interceptor, using a dynamic proxy, may be configured so that a CacheExceptionHandler can
be configured to intercept Exceptions. Errors are not intercepted.

It is configured as per the following example:

  <cacheExceptionHandlerFactory class="com.example.ExampleExceptionHandlerFactory"
                                  properties="logLevel=FINE"/>

Caches with ExceptionHandling configured are not of type Cache, but are of type Ehcache
only, and are not available using CacheManager.getCache(), but using
CacheManager.getEhcache().


Cache Loader

A default CacheLoader may be set which loads objects into the cache through asynchronous
 and synchronous methods on Cache. This is different to the bootstrap cache loader, which
 is used only in distributed caching.

It is configured as per the following example:

    <cacheLoaderFactory class="com.example.ExampleCacheLoaderFactory"
                                  properties="type=int,startCounter=10"/>

Cache Extension

CacheExtensions are a general purpose mechanism to allow generic extensions to a Cache.
CacheExtensions are tied into the Cache lifecycle.

CacheExtensions are created using the CacheExtensionFactory which has a
<code>createCacheCacheExtension()</code> method which takes as a parameter a
Cache and properties. It can thus call back into any public method on Cache, including, of
course, the load methods.

Extensions are added as per the following example:

     <cacheExtensionFactory class="com.example.FileWatchingCacheRefresherExtensionFactory"
                         properties="refreshIntervalMillis=18000, loaderTimeout=3000,
                                     flushPeriod=whatever, someOtherProperty=someValue ..."/>

Terracotta Clustering

Cache elements can also contain information about whether the cache can be clustered with
Terracotta. The <terracotta> sub-element has the following attributes:

* clustered=true|false - indicates whether this cache should be clustered with Terracotta.
  By default, if the <terracotta> element is included, clustered=true.
* valueMode=serialization|identity - indicates whether this cache should be clustered with
  serialized copies of the values or using Terracotta identity mode.  By default, values
  will be cached in serialization mode which is similar to other replicated Ehcache modes.
  The identity mode is only available in certain Terracotta deployment scenarios and will
  maintain actual object identity of the keys and values across the cluster.  In this case,
  all users of a value retrieved from the cache are using the same clustered value and must
  provide appropriate locking for any changes made to the value (or objects referred to by
  the value).
* coherentReads=true|false - indicates whether this cache should have coherent reads with
  guaranteed consistency across the cluster.  By default, this setting is true.  If you set
  this property to false, reads are allowed to check the local value without locking,
  possibly seeing stale values. This is a performance optimization with weaker concurrency
  guarantees and should generally be used with caches that contain read-only data or where
  the application can tolerate reading stale data.
* localKeyCache=true|false - indicates whether this cache should use a local key cache on
  each client.  This caches the translations from the external object keys to the string
  keys used internally by the Terracotta clustered store.  This option is disabled by
  default, and is generally only useful for small read-only caches.
* localKeyCacheSize=integer - indicates the maximum size of the local key cache.  When using
  a local key cache this should be set to the size of the local key set (either the cache
  size or the partition size).
* orphanEviction=true|false - indicates whether orphan eviction is enabled for this cache.
  Orphan eviction is the removal of cache elements that are not present in any client, but
  are present on the Terracotta server array.  This option is enabled by default, and should
  only be enabled if you are certain that you have no need for orphan eviction.
* orphanEvictionPeriod=integer - indicates the period of the orphan eviction cycles, measured
  in local eviction periods.  The default value of 4 indicates that an orphan eviction cycle
  will occur after every fourth local eviction cycle.

The simplest example to indicate clustering:

    <terracotta/>

To indicate the cache should not be clustered (or remove the <terracotta> element
 altogether):

    <terracotta clustered="false"/>

To indicate the cache should be clustered using identity mode:

    <terracotta clustered="true" valueMode="identity"/>
-->

<!--
Mandatory Default Cache configuration. These settings will be applied to caches
created programmtically using CacheManager.add(String cacheName).

The defaultCache has an implicit name "default" which is a reserved cache name.
-->
<defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        diskSpoolBufferSizeMB="30"
        maxElementsOnDisk="10000000"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU"
        />

<!--
Sample caches. Following are some example caches. Remove these before use.
-->

<!--
Sample cache named sampleCache1
This cache contains a maximum in memory of 10000 elements, and will expire
an element if it is idle for more than 5 minutes and lives for more than
10 minutes.

If there are more than 10000 elements it will overflow to the
disk cache, which in this configuration will go to wherever java.io.tmp is
defined on your system. On a standard Linux system this will be /tmp"
-->
<cache name="sampleCache1"
       maxElementsInMemory="10000"
       maxElementsOnDisk="1000"
       eternal="false"
       overflowToDisk="true"
       diskSpoolBufferSizeMB="20"
       timeToIdleSeconds="300"
       timeToLiveSeconds="600"
       memoryStoreEvictionPolicy="LFU"
        />


<!--
Sample cache named sampleCache2
This cache has a maximum of 1000 elements in memory. There is no overflow to disk, so 1000
is also the maximum cache size. Note that when a cache is eternal, timeToLive and
timeToIdle are not used and do not need to be specified.
-->
<cache name="sampleCache2"
       maxElementsInMemory="1000"
       eternal="true"
       overflowToDisk="false"
       memoryStoreEvictionPolicy="FIFO"
        />


<!--
Sample cache named sampleCache3. This cache overflows to disk. The disk store is
persistent between cache and VM restarts. The disk expiry thread interval is set to 10
minutes, overriding the default of 2 minutes.
-->
<cache name="sampleCache3"
       maxElementsInMemory="500"
       eternal="false"
       overflowToDisk="true"
       timeToIdleSeconds="300"
       timeToLiveSeconds="600"
       diskPersistent="true"
       diskExpiryThreadIntervalSeconds="1"
       memoryStoreEvictionPolicy="LFU"
        />


<!--
Sample distributed cache named sampleDistributedCache1.
This cache replicates using defaults.
It also bootstraps from the cluster, using default properties.
-->
<cache name="sampleDistributedCache1"
       maxElementsInMemory="10"
       eternal="false"
       timeToIdleSeconds="100"
       timeToLiveSeconds="100"
       overflowToDisk="false">

    <cacheEventListenerFactory
            class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
    <bootstrapCacheLoaderFactory
            class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"/>
</cache>


<!--
Sample distributed cache named sampleDistributedCache2.
This cache replicates using specific properties.
It only replicates updates and does so synchronously via copy
-->
<cache name="sampleDistributedCache2"
       maxElementsInMemory="10"
       eternal="false"
       timeToIdleSeconds="100"
       timeToLiveSeconds="100"
       overflowToDisk="false">
    <cacheEventListenerFactory
            class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
            properties="replicateAsynchronously=false, replicatePuts=false,
                        replicatePutsViaCopy=false, replicateUpdates=true,
                        replicateUpdatesViaCopy=true, replicateRemovals=false"/>
</cache>

<!--
Sample distributed cache named sampleDistributedCache3.
This cache replicates using defaults except that the asynchronous replication
interval is set to 200ms.
This one includes / and # which were illegal in ehcache 1.5.
-->
<cache name="sample/DistributedCache3"
       maxElementsInMemory="10"
       eternal="false"
       timeToIdleSeconds="100"
       timeToLiveSeconds="100"
       overflowToDisk="true">
    <cacheEventListenerFactory
            class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
            properties="asynchronousReplicationIntervalMillis=200"/>
</cache>

<!--
Sample Terracotta clustered cache named sampleTerracottaCache.
This cache uses Terracotta to cluster the contents of the cache.
-->
<!--
<cache name="sampleTerracottaCache"
       maxElementsInMemory="1000"
       eternal="false"
       timeToIdleSeconds="3600"
       timeToLiveSeconds="1800"
       overflowToDisk="false">
    <terracotta/>
</cache>
-->



</ehcache>

8.4 Special System PropertiesContents

8.4.1 net.sf.ehcache.disabledContents

Setting this System Property to true disables caching in ehcache. If disabled no elements will be added to a cache. i.e. puts are silently discarded.

e.g. java -Dnet.sf.ehcache.disabled=true in the Java command line.

8.4.2 net.sf.ehcache.use.classic.lruContents

Set this System property to true to use the older LruMemoryStore implementation when LRU is selected as the eviction policy.

This is provided for ease of migration.

e.g. java -Dnet.sf.ehcache.use.classic.lru=true in the Java command line. --- Storage Options ---

9 Storage OptionsContents

Ehcache has two stores:

9.1 Memory StoreContents

The MemoryStore is always enabled. It is not directly manipulated, but is a component of every cache.

9.1.1 Memory Use, Spooling and Expiry StrategyContents

All caches specify their maximum in-memory size, in terms of the number of elements, at configuration time.

When an element is added to a cache and it goes beyond its maximum memory size, an existing element is either deleted, if overflowToDisk is false, or evaluated for spooling to disk, if overflowToDisk is true. In the latter case, a check for expiry is carried out. If it is expired it is deleted; if not it is spooled. The eviction of an item from the memory store is based on the MemoryStoreEvictionPolicy setting specified in the configuration file.

memoryStoreEvictionPolicy is an optional attribute in ehcache.xml introduced since 1.2. Legal values are LRU (default), LFU and FIFO.

LRU, LFU and FIFO eviction policies are supported. LRU is the default, consistent with all earlier releases of ehcache.

9.2 DiskStoreContents

The DiskStore provides a disk spooling facility.

9.2.1 DiskStores are OptionalContents

The diskStore element in ehcache.xml is now optional (as of 1.5). If all caches use only MemoryStores, then there is no need to configure a diskStore. This simplifies configuration, and uses less threads. It is also good where where multiple CacheManagers are being used, and multiple disk store paths would need to be configured.

If one or more caches requires a DiskStore, and none is configured, java.io.tmpdir will be used and a warning message will be logged to encourage explicity configuration of the diskStore path.

9.2.1.1 Turning off disk stores

To turn off disk store path creation, comment out the diskStore element in ehcache.xml.

The ehcache-failsafe.xml configuration uses a disk store. This will remain the case so as to not affect existing Ehcache deployments. So, if you do not wish to use a disk store make sure you specify your own ehcache.xml and comment out the diskStore element.

9.2.2 Suitable Element TypesContents

Only Elements which are Serializable can be placed in the DiskStore. Any non serializable Elements which attempt to overflow to the DiskStore will be removed instead, and a WARNING level log message emitted.

9.2.3 StorageContents

9.2.3.1 Files

The disk store creates a data file for each cache on startup called "cache_name.data", and, if the DiskStore is configured to be persistent, an index file called "cache name.index" on flushing of the DiskStore either explicitly using Cache.flush or on CacheManager shutdown.

9.2.3.2 Storage Location

Files are created in the directory specified by the diskStore configuration element. The diskStore configuration for the ehcache-failsafe.xml and bundled sample configuration file ehcache.xml is "java.io.tmpdir", which causes files to be created in the system's temporary directory.

9.2.3.3 diskStore Element

The diskStore element is has one attribute called path. --- diskStore path="java.io.tmpdir"/ --- Legal values for the path attibute are legal file system paths. e.g.for Unix

    /home/application/cache

The following system properties are also legal, in which case they are translated:

9.2.4 ExpiryContents

One thread per cache is used to remove expired elements. The optional attribute diskExpiryThreadIntervalSeconds sets the interval between runs of the expiry thread. Warning: setting this to a low value is not recommended. It can cause excessive DiskStore locking and high cpu utilisation. The default value is 120 seconds.

9.2.5 EvictionContents

If the maxElementsOnDisk attribute is set, elements will be evicted from the DiskStore when it exceeds that amount. The LFU algorithm is used for these evictions. It is not configurable to use another algorithm.

9.2.6 Serializable ObjectsContents

Only Serializable objects can be stored in a DiskStore. A NotSerializableException will be thrown if the object is not serializable.

9.2.7 SafetyContents

DiskStores are thread safe.

9.2.8 PersistenceContents

DiskStore persistence is controlled by the diskPersistent configuration element. If false or omitted, DiskStores will not persist between CacheManager restarts. The data file for each cache will be deleted, if it exists, both on shutdown and startup. No data from a previous instance CacheManager is available.

If diskPersistent is true, the data file, and an index file, are saved. Cache Elements are available to a new CacheManager. This CacheManager may be in the same VM instance, or a new one.

The data file is updated continuously during operation of the Disk Store if overflowToDisk is true. Otherwise it is not updated until either cache.flush() is called or the cache is disposed.

In all cases the index file is only written when dispose is called on the DiskStore. This happens when the CacheManager is shut down, a Cache is disposed, or the VM is being shut down. It is recommended that the CacheManager shutdown() method be used. See Virtual Machine Shutdown Considerations for guidance on how to safely shut the Virtual Machine down.

When a DiskStore is persisted, the following steps take place:

On startup the following steps take place:

These actions favour safety over persistence. Ehcache is a cache, not a database. If a file gets dirty, all data is deleted. Once started there is further checking for corruption. When a get is done, if the Element cannot be successfully derserialized, it is deleted, and null is returned. These measures prevent corrupt and inconsistent data being returned.

--- Cache Eviction Algorithms ---

10 Cache Eviction AlgorithmsContents

10.1 EvictionContents

A cache eviction algorithm is a way of deciding which Element to evict when the cache is full.

In Ehcache the MemoryStore has a fixed limited size set by maxElementsInMemory (unless the maxElementsInMemory is 0, in which case the capacity is unlimited). When the store gets full, elements are evicted. The eviction algorithms in Ehcache determines which elements is evicted. The default is LRU.

What happens on eviction depends on the cache configuration. If a DiskStore is configured, the evicted element will overflow to disk, otherwise it will be removed.

The DiskStore size by default is unbounded. But a maximum size can be set using the maxElementsOnDisk cache attribute. If the DiskStore is full, then adding an element will cause one to be evicted. The DiskStore eviction algorithm is not configurable. It uses LFU.

10.1.1 Supported MemoryStore Eviction AlgorithmsContents

The idea here is, given a limit on the number of items to cache, how to choose the thing to evict that gives the best result.

In 1966 Laszlo Belady showed that the most efficient caching algorithm would be to always discard the information that will not be needed for the longest time in the future. This it a theoretical result that is unimplementable without domain knowledge. The Least Recently Used ("LRU") algorithm is often used as a proxy. It works pretty well because of the locality of reference phenonemon. As a result, LRU is the default eviction algorithm in Ehcache, as it is in most caches.

Ehcache users may sometimes have a good domain knowledge. Accordingly, Ehcache provides three eviction algorithms to choose from for the MemoryStore.

10.1.2 MemoryStore Eviction AlgorithmsContents

The MemoryStore supports three eviction algorithms: LRU, LFU and FIFO.

The default is LRU.

10.1.2.1 Least Recently Used (LRU)

The eldest element, is the Least Recently Used (LRU). The last used timestamp is updated when an element is put into the cache or an element is retrieved from the cache with a get call.

10.1.2.2 Less Frequently Used (LFU)

For each get call on the element the number of hits is updated. When a put call is made for a new element (and assuming that the max limit is reached) the element with least number of hits, the Less Frequently Used element, is evicted.

If cache element use follows a pareto distribution, this algorithm may give better results than LRU.

LFU is an algorithm unique to Ehcache. It takes a random sample of the Elements and evicts the smallest. Using the sample size of 30 elements, empirical testing shows that an Element in the lowest quartile of use is evicted 99.99% of the time.

10.1.2.3 First In First Out (FIFO)

Elements are evicted in the same order as they come in. When a put call is made for a new element (and assuming that the max limit is reached for the memory store) the element that was placed first (First-In) in the store is the candidate for eviction (First-Out).

This algorithm is used if the use of an element makes it less likely to be used in the future. An example here would be an authentication cache.

10.1.3 DiskStore Eviction AlgorithmsContents

The DiskStore uses the Less Frequently Used algorithm to evict an element when it is full.

--- Code Samples ---

11 Code SamplesContents

This page shows some of the more common code samples to get you started. Code samples for each feature are in the relevant chapters.

12 %toc|fromDepth=2|toDepth=3Contents

12.1 Using the CacheManagerContents

All usages of Ehcache start with the creation of a CacheManager.

12.1.1 Singleton versus InstanceContents

As of ehcache-1.2, Ehcache CacheManagers can be created as either singletons (use the create factory method) or instances (use new).

Create a singleton CacheManager using defaults, then list caches.

CacheManager.create();
String[] cacheNames = CacheManager.getInstance().getCacheNames();

Create a CacheManager instance using defaults, then list caches.

 CacheManager manager = new CacheManager();
 String[] cacheNames = manager.getCacheNames();

Create two CacheManagers, each with a different configuration, and list the caches in each.

 CacheManager manager1 = new CacheManager("src/config/ehcache1.xml");
 CacheManager manager2 = new CacheManager("src/config/ehcache2.xml");
 String[] cacheNamesForManager1 = manager1.getCacheNames();
 String[] cacheNamesForManager2 = manager2.getCacheNames();

12.1.2 Ways of loading Cache ConfigurationContents

When the CacheManager is created it creates caches found in the configuration.

Create a CacheManager using defaults. Ehcache will look for ehcache.xml in the classpath.

 CacheManager manager = new CacheManager();

Create a CacheManager specifying the path of a configuration file.

CacheManager manager = new CacheManager("src/config/ehcache.xml");

Create a CacheManager from a configuration resource in the classpath.

URL url = getClass().getResource("/anotherconfigurationname.xml");
CacheManager manager = new CacheManager(url);

Create a CacheManager from a configuration in an InputStream.

InputStream fis = new FileInputStream(new File("src/config/ehcache.xml").getAbsolutePath());
try {
    CacheManager manager = new CacheManager(fis);
} finally {
    fis.close();
}

12.1.3 Adding and Removing Caches ProgrammaticallyContents

You are not just stuck with the caches that were placed in the configuration. You can create and remove them programmatically.

Add a cache using defaults, then use it. The following example creates a cache called testCache, which will be configured using defaultCache from the configuration.

CacheManager singletonManager = CacheManager.create();
singletonManager.addCache("testCache");
Cache test = singletonManager.getCache("testCache");

Create a Cache and add it to the CacheManager, then use it. Note that Caches are not usable until they have been added to a CacheManager.

CacheManager singletonManager = CacheManager.create();
Cache memoryOnlyCache = new Cache("testCache", 5000, false, false, 5, 2);
manager.addCache(memoryOnlyCache);
Cache test = singletonManager.getCache("testCache");

See the cache constructor for the full parameters for a new Cache:

Remove cache called sampleCache1

CacheManager singletonManager = CacheManager.create();
singletonManager.removeCache("sampleCache1");

12.1.4 Shutdown the CacheManagerContents

Ehcache should be shutdown after use. It does have a shutdown hook, but it is best practice to shut it down in your code.

Shutdown the singleton CacheManager

CacheManager.getInstance().shutdown();

Shutdown a CacheManager instance, assuming you have a reference to the CacheManager called manager

manager.shutdown();

See the CacheManagerTest for more examples.

12.2 Creating Caches ProgrammaticallyContents

12.2.1 Creating a new cache from defaultsContents

A new cache with a given name can be created from defaults very simply:

manager.addCache(cache name);

12.2.2 Creating a new cache with custom parametersContents

The configuration for a Cache can be specified programmatically as an argument to the Cache constructor:

public Cache(CacheConfiguration cacheConfiguration) {
    ...
   }

Here is an example which creates a cache called test.

   //Create a CacheManager using defaults
   CacheManager manager = CacheManager.create();

   //Create a Cache specifying its configuration.

   Cache testCache = new Cache(
     new CacheConfiguration("test", maxElements)
       .memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LFU)
       .overflowToDisk(true)
       .eternal(false)
       .timeToLiveSeconds(60)
       .timeToIdleSeconds(30)
       .diskPersistent(false)
       .diskExpiryThreadIntervalSeconds(0));
   manager.addCache(cache);

Once the cache is created, add it to the list of caches managed by the CacheManager:

     manager.addCache(testCache);

The cache is not usable until it has been added.

12.3 Using CachesContents

All of these examples refer to manager, which is a reference to a CacheManager, which has a cache in it called sampleCache1.

12.3.1 Obtaining a reference to a CacheContents

Obtain a Cache called "sampleCache1", which has been preconfigured in the configuration file

Cache cache = manager.getCache("sampleCache1");

12.3.2 Performing CRUD operationsContents

Put an element into a cache

Cache cache = manager.getCache("sampleCache1");
Element element = new Element("key1", "value1");
cache.put(element);

Update an element in a cache. Even though cache.put() is used, Ehcache knows there is an existing element, and considers the put an update for the purpose of notifying cache listeners.

Cache cache = manager.getCache("sampleCache1");
cache.put(new Element("key1", "value1"));
//This updates the entry for "key1"
cache.put(new Element("key1", "value2"));

Get a Serializable value from an element in a cache with a key of "key1".

Cache cache = manager.getCache("sampleCache1");
Element element = cache.get("key1");
Serializable value = element.getValue();

Get a NonSerializable value from an element in a cache with a key of "key1".

Cache cache = manager.getCache("sampleCache1");
Element element = cache.get("key1");
Object value = element.getObjectValue();

Remove an element from a cache with a key of "key1".

Cache cache = manager.getCache("sampleCache1");
cache.remove("key1");

12.3.3 Disk Persistence on demandContents

sampleCache1 has a persistent diskStore. We wish to ensure that the data and index are written immediately.

Cache cache = manager.getCache("sampleCache1");
cache.flush();

12.3.4 Obtaining Cache SizesContents

Get the number of elements currently in the Cache.

Cache cache = manager.getCache("sampleCache1");
int elementsInMemory = cache.getSize();

Get the number of elements currently in the MemoryStore.

Cache cache = manager.getCache("sampleCache1");
long elementsInMemory = cache.getMemoryStoreSize();

Get the number of elements currently in the DiskStore.

Cache cache = manager.getCache("sampleCache1");
long elementsInMemory = cache.getDiskStoreSize();

12.3.5 Obtaining Statistics of Cache Hits and MissesContents

These methods are useful for tuning cache configurations.

Get the number of times requested items were found in the cache. i.e. cache hits

Cache cache = manager.getCache("sampleCache1");
int hits = cache.getHitCount();

Get the number of times requested items were found in the MemoryStore of the cache.

Cache cache = manager.getCache("sampleCache1");
int hits = cache.getMemoryStoreHitCount();

Get the number of times requested items were found in the DiskStore of the cache.

Cache cache = manager.getCache("sampleCache1");
int hits = cache.getDiskStoreCount();

Get the number of times requested items were not found in the cache. i.e. cache misses.

Cache cache = manager.getCache("sampleCache1");
int hits = cache.getMissCountNotFound();

Get the number of times requested items were not found in the cache due to expiry of the elements.

Cache cache = manager.getCache("sampleCache1");
int hits = cache.getMissCountExpired();

These are just the most commonly used methods. See CacheTest for more examples. See Cache for the full API.

12.3.6 JTAContents

A cache will automatically participate in the ongoing UserTransaction when configured in transactionalMode XA. This can be done programmatically:

    //Create a CacheManager using defaults
    CacheManager manager = CacheManager.create();

    //Create a Cache specifying its configuration.
    Cache xaCache = new Cache(
            new CacheConfiguration("test", 1000)
                .overflowToDisk(true)
                .eternal(false)
                .transactionalMode(CacheConfiguration.TransactionalMode.XA)
                .terracotta(new TerracottaConfiguration().clustered(true)));
    manager.addCache(xaCache);

Or in your CacheManager's configuration file :

    <cache name="xaCache"
        maxElementsInMemory="500"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="false"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="1"
        transactionalMode="xa">
      <terracotta clustered="true"/>
        </cache>

Please note that XA Transactional caches are currently only supported when clustered with Terracotta.

The Cache can then be used without any special requirement. Changes will only become visible to others, once the transaction has been committed.

    Ehcache cache = cacheManager.getEhcache("xaCache");

    transactionManager.begin();

    try {
      Element e = cache.get(key);

      Object result = complexeService.doStuff(element.getValue());

      // This put will be rolled back should complexeService.doMoreStuff throw an Exception
      cache.put(new Element(key, result));

      // Any changes to result in that call, will be visible to others when the Transaction commits
      complexeService.doMoreStuff(result);

      transactionManager.commit();
    } catch (Exception e) {
      transactionManager.rollback();
    }

12.4 Dynamically Modifying Cache ConfigurationsContents

This example shows how to dynamically modify the cache configuration of an already running cache:

    Cache cache = manager.getCache("sampleCache");
    CacheConfiguration config = cache.getCacheConfiguration();
    config.setTimeToIdleSeconds(60);
    config.setTimeToLiveSeconds(120);
    config.setMaxElementsInMemory(10000);
    config.setMaxElementsOnDisk(1000000);

Dynamic cache configurations can also be frozen to prevent future changes:

    Cache cache = manager.getCache("sampleCache");
    cache.disableDynamicFeatures();

12.5 Registering CacheStatistics in an MBeanServerContents

This example shows how to register CacheStatistics in the JDK1.5 platform MBeanServer, which works with the JConsole management agent.

    CacheManager manager = new CacheManager();
    MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
    ManagementService.registerMBeans(manager, mBeanServer, false, false, false, true);

12.6 Browse the JUnit TestsContents

Ehcache comes with a comprehensive JUnit test suite, which not only tests the code, but shows you how to use ehcache.

A link to browsable unit test source code for the major Ehcache classes is given per section. The unit tests are also in the src.zip in the Ehcache tarball.

12.7 JCache ExamplesContents

See the examples in the JCache Chapter.

12.8 Terracotta ExampleContents

See the fully worked examples in the Terracotta Clustering Chapter.

12.9 Cache Server ExamplesContents

See the examples in the Cache Server Chapter. --- Java Requirements and Dependencies ---

13 Java Requirements and DependenciesContents

13.1 Java RequirementsContents

Current Ehcache releases require Java 1.5 and 1.6 at runtime.

Ehcache 1.5 requires Java 1.4.

The Ehcache DX product which provides management and monitoring will work with Ehcache 1.2.3 but only for Java 1.5 or higher.

13.2 Mandatory DependenciesContents

Ehcache core 1.6 through to 1.7.0 has no dependencies.

Ehcache core 1.7.1 depends on SLF4J (http://www.slf4j.org), an increasingly commonly used logging framework which provides a choice of concrete logging implementation. See the chapter on Logging for configuration details.

Other modules have dependencies as specified in their maven poms.

--- Logging ---

14 LoggingContents

14.1 SLF4J LoggingContents

As of 1.7.1, Ehcache uses the the slf4j (http://www.slf4j.org) logging facade. Plug in your own logging framework.

14.1.1 Concrete Logging Implementation Use in MavenContents

With slf4j, users must choose a concrete logging implementation at deploy time.

The maven dependency declarations are reproduced here for convenience. Add one of these to your Maven pom.

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-jdk14</artifactId>
            <version>1.5.8</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.5.8</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.5.8</version>
        </dependency>

14.1.2 Concrete Logging Implemenation Use in the Download KitContents

We provide the slf4j-api and slf4j-jdk14 jars in the kit along with the ehcache jars so that, if the app does not already use SLF4J, you have everything you need.

Additional concrete logging implementations can be downloaded from http://www.slf4j.org.

14.2 Recommended Logging LevelsContents

Ehcache seeks to trade off informing production support developers or important messages and cluttering the log.

ERROR ERROR messages should not occur in normal production and indicate that action should be taken.

WARN WARN messages generally indicate a configuration change should be made or an unusual event has occurred.

DEBUG DEBUG and TRACE messages are for development use. All DEBUG level statements are surrounded with a guard so that no performance cost is incurred unless the logging level is set.

Setting the logging level to DEBUG should provide more information on the source of any problems. Many logging systems enable a logging level change to be made without restarting the application.

--- Remote Network debugging and monitoring for Distributed Caches ---

15 Remote Network debugging and monitoring for Distributed CachesContents

15.1 IntroductionContents

The ehcache-1.x-remote-debugger.jar} can be used to debug replicated cache operations. When started with the same configuration as the cluster, it will join the cluster and then report cluster events for the cache of interest. By providing a window into the cluster it can help to identify the cause of cluster problems.

15.2 PackagingContents

From version 1.5 it is packaged in its own distribution tarball along with a maven module.

It is provided as an executable jar.

15.3 LimitationsContents

This version of the debugger has been tested only with the default RMI based replication.

15.4 UsageContents

It is invoked as follows:

java -classpath [add your application jars here]
 -jar ehcache-debugger-1.5.0.jar ehcache.xml sampleCache1
    path_to_ehcache.xml [cacheToMonitor]

Note: Add to the classpath any libraries your project uses in addition to these above, otherwise RMI will attempt to load them remotely which requires specific security policy settings that surprise most people.

It takes one or two arguments:

15.4.1 OutputContents

When monitoring a cache it prints a list of caches with replication configured, prints notifications as they happen, and periodically prints the cache name, size and total events received. See sample output below which is produced when the RemoteDebuggerTest is run.

   Caches with replication configured which are available for monitoring are:
   sampleCache19 sampleCache20 sampleCache26 sampleCache42 sampleCache33
   sampleCache51 sampleCache40 sampleCache32 sampleCache18 sampleCache25
   sampleCache9 sampleCache15 sampleCache56 sampleCache31 sampleCache7
   sampleCache12 sampleCache17 sampleCache45 sampleCache41 sampleCache30
   sampleCache13 sampleCache46 sampleCache4 sampleCache36 sampleCache29
   sampleCache50 sampleCache37 sampleCache49 sampleCache48 sampleCache38
   sampleCache6 sampleCache2 sampleCache55 sampleCache16 sampleCache27
   sampleCache11 sampleCache3 sampleCache54 sampleCache28 sampleCache10
   sampleCache8 sampleCache47 sampleCache5 sampleCache53 sampleCache39
   sampleCache23 sampleCache34 sampleCache22 sampleCache44 sampleCache52
   sampleCache24 sampleCache35 sampleCache21 sampleCache43 sampleCache1
   Monitoring cache: sampleCache1
   Cache: sampleCache1 Notifications received: 0 Elements in cache: 0
   Received put notification for element [ key = this is an id, value=this is
   a value, version=1, hitCount=0, CreationTime = 1210656023456,
   LastAccessTime = 0 ]
   Received update notification for element [ key = this is an id, value=this
   is a value, version=1210656025351, hitCount=0, CreationTime =
   1210656024458, LastAccessTime = 0 ]
   Cache: sampleCache1 Notifications received: 2 Elements in cache: 1
   Received remove notification for element this is an id
   Received removeAll notification.

15.4.2 Providing more Detailed LoggingContents

If you see nothing happening, but cache operations should be going through, enable trace (LOG4J) or finest (JDK) level logging on codenet.sf.ehcache.distribution/code in the logging configuration being used by the debugger. A large volume of log messages will appear. The normal problem is that the CacheManager has not joined the cluster. Look for the list of cache peers.

15.4.3 Yes, but I still have a cluster problemContents

Check the FAQ where a lot of commonly reported errors and their solutions are provided. Beyond that, post to the forums or mailing list or contact Ehcache for support.

--- Tuning Garbage Collection ---

16 Tuning Garbage CollectionContents

Applications which use Ehcache can be expected to have larger heaps. Some Ehcache applications have heap sizes greater than 6GB.

Ehcache works well at this scale. However large heaps or long held object, which is what a cache is, can place strain on the default Garbage Collector.

Note. The following documentation relates to Sun JDK 1.5.

16.1 Detecting Garbage Collection ProblemsContents

A full garbage collection event pauses all threads in the JVM. Nothing happens during the pause. If this pause takes more than a few seconds it will become noticeable.

The clearest way to see if this is happening is to run jstat. The following command will produce a log of garbage collection statistics, updated each ten seconds.

    jstat -gcutil <pid> 10 1000000

The thing to watch for is the Full Garbage Collection Time. The difference between the total time for each reading is the time the system spends time paused. If there is a jump more than a few seconds this will not be acceptable in most application contexts.

16.2 Garbage Collection TuningContents

The Sun core garbage collection team has offered the following tuning suggestion for virtual machines with large heaps using caching:

java ... -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC
    -XX:NewSize=<1/4 of total heap size> -XX:SurvivorRatio=16

The reasoning for each setting is as follows:

16.3 Distributed Caching Garbage Collection TuningContents

Some users have reported that enabling distributed caching causes a full GC each minute. This is an issue with RMI generally, which can be worked around by increasing the interval for garbage collection. The effect that RMI is having is similar to a user application calling System.gc() each minute. In the settings above this is disabled, but it does not disable the full GC initiated by RMI.

The default in JDK6 was increased to 1 hour. The following system properties control the interval.

-Dsun.rmi.dgc.client.gcInterval=60000
-Dsun.rmi.dgc.server.gcInterval=60000

See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4403367 for the bug report and detailed instructions on workarounds.

Increase the interval as required in your application.

--- JMX Management and Monitoring ---

17 JMX Management and MonitoringContents

17.1 Terracotta Monitoring ProductsContents

An extensive new monitoring product, available in Ehcache DX, provides a monitoring server with probes supporting Ehcache-1.2.3 and higher for standalone and clustered Ehcache. It comes with a web console and a RESTful API for operations integration.

See the Ehcache DX documentation for more information.

When using Ehcache 1.7 with Terracotta clustering, the Terracotta Developer Console shows statistics for ehcache.

17.2 JMX OverviewContents

JMX, part of JDK1.5, and available as a download for 1.4, creates a standard way of instrumenting classes and making them available to a management and monitoring infrastructure.

The net.sf.ehcache.management package contains MBeans and a ManagementService for JMX management of ehcache. It is in a separate package so that JMX libraries are only required if you wish to use it - there is no leakage of JMX dependencies into the core Ehcache package.

This implementation attempts to follow Sun's JMX best practices. See http://java.sun.com/javase/technologies/core/mntr-mgmt/ javamanagement/best-practices.jsp.

Use net.sf.ehcache.management.ManagementService.registerMBeans(...) static method to register a selection of MBeans to the MBeanServer provided to the method.

If you wish to monitor Ehcache but not use JMX, just use the existing public methods on Cache and CacheStatistics.

images/uml/management_package

The Management Package

17.3 MBeansContents

Ehcache uses Standard MBeans. MBeans are available for the following:

17.4 JMX RemotingContents

The JMX Remote API allows connection from a remote JMX Agent to an MBeanServer via an MBeanServerConnection.

Only Serializable attributes are available remotely. The following Ehcache MBean attributes are available remotely:

17.5 ObjectName naming schemeContents

17.6 The Management ServiceContents

The ManagementService class is the API entry point.

images/uml/ManagementService

ManagementService

There is only one method, ManagementService.registerMBeans which is used to initiate JMX registration of an Ehcache CacheManager's instrumented MBeans.

The ManagementService is a CacheManagerEventListener and is therefore notified of any new Caches added or disposed and updates the MBeanServer appropriately.

Once initiated the MBeans remain registered in the MBeanServer until the CacheManager shuts down, at which time the MBeans are deregistered. This behaviour ensures correct behaviour in application servers where applications are deployed and undeployed.

/**
 * This method causes the selected monitoring options to be be registered
 * with the provided MBeanServer for caches in the given CacheManager.
 * <p/>
 * While registering the CacheManager enables traversal to all of the other
 *  items,
 * this requires programmatic traversal. The other options allow entry points closer
 * to an item of interest and are more accessible from JMX management tools like JConsole.
 * Moreover CacheManager and Cache are not serializable, so remote monitoring is not
 * possible * for CacheManager or Cache, while CacheStatistics and CacheConfiguration are.
 * Finally * CacheManager and Cache enable management operations to be performed.
 * <p/>
 * Once monitoring is enabled caches will automatically added and removed from the
 * MBeanServer * as they are added and disposed of from the CacheManager. When the
 * CacheManager itself * shutsdown all registered MBeans will be unregistered.
 *
 * @param cacheManager the CacheManager to listen to
 * @param mBeanServer the MBeanServer to register MBeans to
 * @param registerCacheManager Whether to register the CacheManager MBean
 * @param registerCaches Whether to register the Cache MBeans
 * @param registerCacheConfigurations Whether to register the CacheConfiguration MBeans
 * @param registerCacheStatistics Whether to register the CacheStatistics MBeans
 */
public static void registerMBeans(
        net.sf.ehcache.CacheManager cacheManager,
        MBeanServer mBeanServer,
        boolean registerCacheManager,
        boolean registerCaches,
        boolean registerCacheConfigurations,
        boolean registerCacheStatistics) throws CacheException {

17.7 JConsole ExampleContents

This example shows how to register CacheStatistics in the JDK1.5 platform MBeanServer, which works with the JConsole management agent.

    CacheManager manager = new CacheManager();
    MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
    ManagementService.registerMBeans(manager, mBeanServer, false, false, false, true);

CacheStatistics MBeans are then registered.

images/JConsoleExample

CacheStatistics MBeans in JConsole

17.8 Hibernate statisticsContents

If you are running Terracotta clustered caches as hibernate second-level cache provider, it is possible to access the hibernate statistics + ehcache stats etc via jmx.

EhcacheHibernateMBean is the main interface that exposes all the API's via jmx. It basically extends two interfaces -- EhcacheStats and HibernateStats. And as the name implies EhcacheStats contains methods related with Ehcache and HibernateStats related with Hibernate.

You can see cache hit/miss/put rates, change config element values dynamically -- like maxElementInMemory, TTI, TTL, enable/disable statistics collection etc and various other things. Please look into the specific interface for more details.

17.9 JMX TutorialContents

See http://weblogs.java.net/blog/maxpoon/archive/2007/06/extending_the_n_2.html for an online tutorial.

--- JTA ---

18 JTAContents

New feature in Ehcache 2.0 JTA is supported in versions of Ehcache 2.0 and higher.

Ehcache acts as an XAResouce and participates in JTA ("Java Transaction API") transactions.

18.1 Transaction ManagersContents

18.1.1 Automatically Detected Transaction ManagersContents

Ehcache automatically detects and uses the following transaction managers in the following order:

No configuration is required; they work out of the box.

The first found is used.

18.1.2 Configuring a Transaction ManagerContents

If you Transaction Manager is not in the above list or you wish to change the priority you need to configure your own lookup class and specify it in place of the DefaultTransactionManagerLookup in the ehcache.xml config::

<transactionManagerLookup
 class= "net.sf.ehcache.transaction.manager.DefaultTransactionManagerLookup"
 properties="" propertySeparator=":"/>

You can also provide a different location for the JNDI lookup by providing the jndiName property to the DefaultTransactionManagerLookup.

The example below provides the proper location for the TransactionManager in GlassFish v3:

<transactionManagerLookup
 class="net.sf.ehcache.transaction.manager.DefaultTransactionManagerLookup"
 properties="jndiName=java:appserver/TransactionManager" propertySeparator=";"/>

18.2 Configuring a Cache for JTAContents

JTA is enabled on a cache by cache basis with the transactionalMode cache attribute

The allowed values are xa and off. By default it is off.

Enabling a cache for JTA is shown in the following example:

    <cache name="xaCache"
        maxElementsInMemory="500"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="false"
        diskPersistent="false"
        diskExpiryThreadIntervalSeconds="1"
        transactionalMode="xa">
      <terracotta clustered="true"/>
  </cache>

Note that in Ehcache 2.0 JTA requires Terracotta serialization value mode otherwise a a CacheException will be thrown on start up. We plan to support standalone Ehcache in the next release.

18.3 Using a JTA CacheContents

18.3.1 All or nothingContents

If a cache is enabled for JTA all operations on it must happen within a transaction context, otherwise a TransactionRequiredException will be thrown.

18.3.2 Change VisibilityContents

The isolation level offered in Ehcache JTA is READ_COMMITTED. Ehcache is an XAResource. Full two-phase commit is supported.

Specifically:

18.3.3 Write-behind and Write-throughContents

If your XA enabled cache is being used with a writer, write operations will be queued until transaction commit time. Solely a Write-through approach would have its potential XAResource participate in the same transaction. Write-behind, while supported, should probably not be used with an XA transactional Cache, as the operations would never be part of the same transaction. Your writer would also be responsible for obtaining a new transaction...

Using Write-through with a non XA resource would also work, but there is no guarantee the transaction will succeed after the write operation have been executed successfully. On the other hand, any thrown exception during these write operations would cause the transaction to be rolled back by having UserTransaction.commit() throw a RollbackException.

18.4 ArchitectureContents

18.4.1 BootstrappingContents

Transactional support is implemented at the Store level, through XaTransactionalStore. The store actually decorates the underlying MemoryStore implementation, augmenting it with transaction isolation and two-phase commit support.

During it's initialization, the Cache will lookup the TransactionManager using the provided TransactionManagerLookup implementation. Using the TransactionManagerLookup.register(XAResouce): void callback, the newly created XAResource is potentially registered with the TransactionManager.

That same TransactionManager will from there on be used by the Cache to access the current transaction on all transactional method calls.

The store is automatically configured to copy every Element read from the cache or written to it. Cache is copy-on-read and copy-on-write.

18.4.2 A day in the life of a transactional CacheContents

Every read from the Cache, or remove() without a previous get(), will have the transactional track versioning information for these cache values. This version information will be checked against at commit time, to make sure we're still mutating the same information.

Write operation to the cache (puts and removes) are not effectively executed against the underlying memory store. Rather a local transaction context is being altered. It queues all commands to be executed against the Store at commit time. This context also alters the behavior of cache accesses: e.g. within the same transaction a put and then a getSize call will reflect that previous put, while other transaction would not be impacted. This gives read_commited isolation.

During the two phase commit, the context is first prepared: where all keys to be altered are checked for consistency against the optimistic locking mechanism. If a key to be updated or removed has since been changed by a commited transaction, the transaction will be rolled back. For each key a write lock is acquired, version checked and the old value is copied to a temporary "guarding" store. That store is always queried before the real underlying memory store is. That way, while write locked, old values that are about to be updated can still be read, non blocking, from the "oldVersionStore". If all keys could be validated and write locked the prepare operation as finished successfully and Ehcache votes OK on commit.

If all other XAResource eventually vote OK, the transaction is committed: the old value(s) are removed and write-locks are released. If not, the old values are copied back to the store and the lock released.

18.5 FailureContents

As specified by the JTA specification, only prepared transaction data is recoverable. Which means that any transaction still alive at VM failure will be lost. Since all these operations are non locking, the cluster isn't suffering from these.

Prepared data on the other hand, is persisted to the L2 and locks on the memory are being held. Should the L1 come back up before the locks timed out, like network failure, the VM will be able to keep doing its work.

18.5.1 RecoveryContents

Should the XA recovery scan be required by the transaction manager, Ehcache will provide all Xid prepared, but these will only be able to be rolled back. Indeed when locks time out, no guarantee can be made about the locked keys and their value. If the transaction manager still asks Ehcache to commit these, a HeuristicException will be thrown.

18.6 Sample AppsContents

We have three sample applications showing how to use JTA with a variety of technologies.

18.6.1 JTA Sample AppContents

This sample application uses JBoss application server. It shows an example using User managed transactions. While we expect most people will use JTA from within Spring or EJB where the container rather than managing it themselves, it clearly shows what is going on.

The following snippet from our SimpleTX servlet shows a complete transaction.

   Ehcache cache = cacheManager.getEhcache("xaCache");

    UserTransaction ut = getUserTransaction();

    printLine(servletResponse, "Hello...");
    try {
        ut.begin();
        int index = serviceWithinTx(servletResponse, cache);
        printLine(servletResponse, "Bye #" + index);
        ut.commit();

    } catch(Exception e) {
        printLine(servletResponse,
            "Caught a " + e.getClass() + "! Rolling Tx back");
        if(!printStackTrace) {
            PrintWriter s = servletResponse.getWriter();
            e.printStackTrace(s);
            s.flush();
        }
        rollbackTransaction(ut);
    }

The source code for the demo can be checked out from http://svn.terracotta.org/svn/forge/projects/ehcache-jta-sample/trunk Terracotta Community Login Required

A README.txt explains how to get the JTA Sample app going.

18.6.2 JTA Banking ApplicationContents

The Idea of this application is to show a real world scenario. AwWeb app reads account transfer messages from a queue and tries to execute these account transfers.

With JTA turned on, failures are rolled back so that the cached account balance is always the same as the true balance summed from the database.

This app is a Spring-based Java web app running in a Jetty container. It has (embedded) the following components:

18.6.3 ExaminatorContents

Examinator is our complete application that shows many aspects of caching in one web based Exam application, all using the Terracotta Server Array.

Check out from http://svn.terracotta.org/svn/forge/projects/exam/ Terracotta Community Login Required

18.7 LimitationsContents

There are two limitations in this first release of JTA for Ehcache.

18.7.1 Terracotta Clusters onlyContents

It only has effect then using Ehcache with the Terracotta Server Array ("TSA"). We are planning to add support for standalone Ehcache will be added in the next release. Doing so will require implementing copy on read and copy on write functionality into the core which is not yet present.

18.7.2 Hibernate TransactionsContents

Ehcache is not a "transactional" cache for Hibernate purposes. We expect to add that in the next release.

18.8 FAQContents

18.8.1 How do I make WebLogic 10 work with Ehcache JTA?Contents

WebLogic uses an optimization that is not supported by our implementation. By default WebLogic 10 will spawn threads to start the Transaction on each XAResource in parallel. As we need transaction work to be performed on the same Thread, you will have to turn this optimization off by setting parallel-xa-enabled option to false in your domain configuration :

  <jta>
    ...
    <checkpoint-interval-seconds>300</checkpoint-interval-seconds>
    <parallel-xa-enabled>false</parallel-xa-enabled>
    <unregister-resource-grace-period>30</unregister-resource-grace-period>
    ...
  </jta>

--- Ehcache Monitor ---

19 Ehcache MonitorContents

20 %toc|fromDepth=2|toDepth=2Contents

This add-on tool for Ehcache is designed to provide enterprise-class monitoring and management capabilities for use in both development and production. It is intended to help understand and tune cache usage, detect errors, and provide an easy to use access point to integrate with production management systems. It provides administrative functionality such as the ability to forcefully remove items from caches.

The package contains a probe and a server. The probe installs with your existing Ehcache cache instance, and communicates to a central server. The server aggregates data from multiple probes. It can be accessed via a simple web UI, as well as a scriptable API. In this way, it is easy to integrate with common third party systems management tools (such as Hyperic, Nagios etc). The probe is designed to be compatible with all versions of Ehcache from 1.4.1 and requires JDK 1.5 or 1.6.

20.1 Installation And ConfigurationContents

First download and extract the Ehcache Monitor package.

The package consists of a lib directory with the probe and monitor server jars, a bin directory with startup and shutdown scripts for the monitor server and an etc directory with an example monitor server configuration file.

20.1.1 ProbeContents

To include the probe in your Ehcache application, you need to perform two steps:

  1. Add the ehcache-probe-version.jar to your application classpath (or war file). Do this in the same way you added the core ehcache jar to your application.
  2. Configure Ehcache to communicate with the probe by specifying the class name of the probe, the address (or hostname), and the port that the monitor will be running on. This is done by adding the following to ehcache.xml:
    <cacheManagerPeerListenerFactory
        class="org.terracotta.ehcachedx.monitor.ProbePeerListenerFactory"
        properties="monitorAddress=localhost, monitorPort=9889" />

20.1.2 MonitorContents

Copy the monitor package to a monitoring server.

To start the monitor, run the startup script provided in the bin directory: startup.sh on Unix and startup.bat on Microsoft Windows. The monitor port selected in this script should match the port specified in ehcache.xml.

The monitor can be configured, including interface, port and security settings, in the etc/ehcache-monitor.conf.

20.2 Using the Web GUIContents

The web-based GUI is available by pointing your browser at http://monitor-host-name:monitor-port/monitor. For a default installation on the local machine, this would be http://localhost:9889/monitor

The GUI contains 4 tabs, described as follows:

20.2.1 Cache ManagersContents

This tab shows aggregate statistics for the cache managers being monitored by probes connected to the monitor server. Double-clicking on any cache manager drills down to the detailed Statistics tab for that manager.

20.2.2 StatisticsContents

This tab shows the statistics being gathered for each cache managed by the selected cache manager.

The Settings button permits you to add additional statistics fields to the display. Note: only displayed fields are collected and aggregated by the probe. Adding additional display fields will increase the processing required for probe and the monitor. The selected settings are stored in a preferences cookie in your browser.

Double-clicking on any cache drills down to the Contents tab for that cache.

20.2.3 ConfigurationContents

This tab shows the key configuration information for each cache managed by the selected cache manager.

20.2.4 ContentsContents

This tab enables you to look inside the cache, search for elements via their keys and remove individual or groups of elements from the cache.

The GUI is set to refresh at the same frequency that the probes aggregate their statistic samples which is every 10 seconds by default. The progress bar at the bottom of the screen indicates the time until the next refresh.

20.3 Using the APIContents

The Monitor provides a API over HTTP on the same port as the Web GUI.

The list of functions supported by the API can be accessed by pointing your browser at http://monitor-host-name:monitor-port/monitor/list. For a default installation on the local machine, this would be http://localhost:9889/monitor/list

The API returns data as either structured XML or plan text. The default format is txt.

For example, the getVersion function returns the software version of the monitor server. It can be called as follows:

http://localhost:9889/monitor/getVersion

or, to receive the results as XML:

http://localhost:9889/monitor/getVersion?format=xml

To query the data collected by the monitor server from scripts that can then be used to pass the data to enterprise system management frameworks, commands such as curl or wget can be used.

For example, on a Linux system, to query the list of probes that a local monitor on the default port is currently aware of, and return the data in XML format, the following command could be used:

    $ curl http://localhost:9889/monitor/listProbes?format=xml

20.4 Known IssuesContents

20.4.1 Internet ExplorerContents

The GUI is designed to work in most browsers. Currently it has been tested in Firefox and Safari and is known not to work in Microsoft Internet Explorer. Wider browser support is planned for future release builds.

20.5 LicensingContents

Unless otherwise indicated, this module is licensed for usage in development.

For details see the license terms in the appropriate LICENSE.txt. To obtain a commercial license for use in production, please contact sales@terracottatech.com

--- Bulk Loading in Ehcache ---

21 Bulk LoadingContents

22 %toc|fromDepth=2|toDepth=2Contents

New feature in Ehcache 2.0 Ehcache has a bulk loading mode that dramatically speeds up bulk loading into caches using the Terracotta Server Array.

22.1 UsesContents

Bulk loading is designed to be used for:

22.2 APIContents

With bulk loading, the API for putting data into the cache stays the same. Just use cache.put(...) cache.load(...) or cache.loadAll(...)>>>.

What changes is that there is a special mode that suspends Terracotta's normal coherence guarantees and provides optimised flushing to the Terracotta Server Array (the L2 cache).

This mode can be enabled programmatically or statically in ehcache.xml. Programmatically, four methods control coherent behaviour: setNodeCoherence(boolean mode), isNodeCoherent(), isClusterCoherent() and waitUntilClusterCoherent().

22.2.1 setNodeCoherence(boolean mode)Contents

setNodeCoherence(false) sets coherence to false for the Ehcache node. The setting for the rest of the cluster stays the same. The effect is that normal read and write locks are not obtained. setNodeCoherence(true) brings back the cache to coherent mode for the node.

22.2.2 isNodeCoherent() Contents

Use this to find out if the node is in coherent mode locally. This does not account for other nodes in the cluster (if any). The node may be coherent while its incoherent cluster-wide (like some other node is incoherent)

22.2.3 isClusterCoherent()Contents

Reflects whether the cache is in coherent or incoherent mode cluster-wide. Coherent cluster-wide means that all nodes in the cluster is using the cache in coherent mode. If even one of the nodes is using the cache in incoherent mode, the cache is incoherent cluster-wide

22.2.4 waitUntilClusterCoherent() Contents

Calling this method will block the calling thread until the cache becomes coherent cluster-wide.

waitUntilClusterCoherent

waits until everyone is coherent. Will not return until the entire cluster is coherent.

setNodeCoherence(true | false)

This affects the local node only. The settings in the rest of the cluster are not affected.

Then to put it back call with true parameter.

This method does not return until all the transactions are flushed to the cluster. Only the calling thread is blocked. This way you know when coherence is restored. This returns as soon DONT SAY. Will make async later.

Everyone block

The initial state is from the config.

In a local standalone cache, setNodeCoherence should throw an UnsupportedOperationException. waitUntilClusterCoherent will also throw an UnsupportedOperationException.

22.3 Speed ImprovementContents

The speed performance improvement is an order of magnitude faster.

ehcacheperf (Spring Pet Clinic) now has a bulk load test which shows the performance improvement for using a Terracotta cluster.

22.4 FAQContents

22.4.1 Why does the bulk loading mode only apply to Terracotta clusters?Contents

Ehcache, both standalone and replicated is already very fast and nothing needed to be added.

22.4.2 How does bulk load with RMI distributed caching work?Contents

The core updates are very fast. RMI updates are batched by default once per second, so bulk loading will be efficiently replicated.

22.5 Performance TipsContents

22.5.1 When to use Multiple Put ThreadsContents

It is not necessary to create multiple threads when calling cache.put. Only a marginal performance improvement will result, because the call is already so fast.

It is only necessary if the source is slow. By reading from the source in multiple threads a speed up could result. An example is a database, where multiple reading threads will often be better.

22.5.2 Bulk Loading on Multiple NodesContents

The implementation scales very well when the load is split up against multiple Ehcache CacheManagers on multiple machines.

You add extra nodes for bulk loading to get up to 93 times performance.

22.5.3 Why not run in bulk load mode all the timeContents

Terracotta clustering provides coherence, scaling and durability. Some applications will require coherence, or not for some caches, such as reference data. It is possible to run a cache permanently in incoherent mode.

In ehcache.xml, set the coherent attribute to false in the terracotta element. The terracotta element is a sub-element of cache, so this can be configured per cache.

22.6 DownloadContents

The bulk loading feature is in the ehcache-core module but only provides a performance improvement to Terracotta clusters (as bulk loading to Ehcache standalone is very fast already)

Download here.

For a full distribution enabling connection to the Terracotta Server array download here.

22.7 Further InformationContents

Saravanan who was the lead on this feature has blogged about it here.

--- Class loading and Class Loaders ---

23 Class loading and Class LoadersContents

Class loading within the plethora of environments Ehcache can be running is a somewhat vexed issue.

Since ehcache-1.2 all classloading is done in a standard way in one utility class: ClassLoaderUtil.

23.1 Plugin class loadingContents

Ehcache allows plugins for events and distribution. These are loaded and created as follows:

/**
 * Creates a new class instance. Logs errors along the way. Classes are loaded using the
 * Ehcache standard classloader.
 *
 * @param className a fully qualified class name
 * @return null if the instance cannot be loaded
 */
public static Object createNewInstance(String className) throws CacheException {
    Class clazz;
    Object newInstance;
    try {
        clazz = Class.forName(className, true, getStandardClassLoader());
    } catch (ClassNotFoundException e) {
        //try fallback
        try {
            clazz = Class.forName(className, true, getFallbackClassLoader());
        } catch (ClassNotFoundException ex) {
            throw new CacheException("Unable to load class " + className +
                    ". Initial cause was " + e.getMessage(), e);
        }
    }

    try {
        newInstance = clazz.newInstance();
    } catch (IllegalAccessException e) {
        throw new CacheException("Unable to load class " + className +
                ". Initial cause was " + e.getMessage(), e);
    } catch (InstantiationException e) {
        throw new CacheException("Unable to load class " + className +
                ". Initial cause was " + e.getMessage(), e);
    }
    return newInstance;
}

/**
 * Gets the <code>ClassLoader</code> that all classes in ehcache, and extensions, should
 * use for classloading. All ClassLoading in Ehcache should use this one. This is the only
 * thing that seems to work for all of the class loading situations found in the wild.
 * @return the thread context class loader.
 */
public static ClassLoader getStandardClassLoader() {
    return Thread.currentThread().getContextClassLoader();
}

/**
 * Gets a fallback <code>ClassLoader</code> that all classes in ehcache, and extensions,
 * should use for classloading. This is used if the context class loader does not work.
 * @return the <code>ClassLoaderUtil.class.getClassLoader();</code>
 */
public static ClassLoader getFallbackClassLoader() {
    return ClassLoaderUtil.class.getClassLoader();
}

If this does not work for some reason a CacheException is thrown with a detailed error message.

23.2 Loading of ehcache.xml resourcesContents

If the configuration is otherwise unspecified, Ehcache looks for a configuration in the following order:

Ehcache uses the first configuration found.

Note the use of "/ehcache.xml" which requires that ehcache.xml be placed at the root of the classpath, i.e. not in any package.

23.3 Classloading with Terracotta clusteringContents

If Terracotta clustering is being used with valueMode="serialization" then keys and values will be moved across the cluster in byte[] and deserialized on other nodes.

The classloaders used (in order) to instantiate those classes will be:

--- Performance Considerations ---

24 Performance ConsiderationsContents

24.1 DiskStoreContents

Ehcache comes with a MemoryStore and a DiskStore. The MemoryStore is approximately an order of magnitude faster than the DiskStore. The reason is that the DiskStore incurs the following extra overhead:

Note that writing to disk is not a synchronous performance overhead because it is handled by a separate thread.

A Cache should alway have its maximumSize attribute set to 1 or higher. A Cache with a maximum size of 1 has twice the performance of a disk only cache, i.e. one where the maximumSize is set to 0. For this reason a warning will be issued if a Cache is created with a 0 maximumSize.

24.2 ReplicationContents

The asynchronous replicator is the highest performance. There are two different effects:

24.3 StatisticsContents

Collection of cache statistics is not entirely free of overhead. In production systems where monitoring is not required statistics can be disabled. This can be done either programatically by calling setStatisticsEnabled(false) on the cache instance, or in configuration by setting the statistics="false" attribute of the relevant cache configuration element. --- Cache Decorators ---

25 Cache DecoratorsContents

Ehcache 1.2 introduced the Ehcache interface, of which Cache is an implementation. It is possible and encouraged to create Ehcache decorators that are backed by a Cache instance, implement Ehcache and provide extra functionality.

The Decorator pattern is one of the the well known Gang of Four patterns.

25.1 Creating a DecoratorContents

Cache decorators are created as follows:

BlockingCache newBlockingCache = new BlockingCache(cache);

The class must implement Ehcache.

25.2 Accessing the decorated cacheContents

Having created a decorator it is generally useful to put it in a place where multiple threads may access it. This can be achieved in multiple ways.

25.2.1 Using CacheManager to access decorated cachesContents

A built-in way is to replace the Cache in CacheManager with the decorated one. This is achieved as in the following example:

cacheManager.replaceCacheWithDecoratedCache(cache, newBlockingCache);

The CacheManager replaceCacheWithDecoratedCache method requires that the decorated cache be built from the underlying cache from the same name.

Note that any overwritten Ehcache methods will take on new behaviours without casting, as per the normal rules of Java. Casting is only required for new methods that the decorator introduces.

Any calls to get the cache out of the CacheManager now return the decorated one.

A word of caution. This method should be called in an appropriately synchronized init style method before multiple threads attempt to use it. All threads must be referencing the same decorated cache. An example of a suitable init method is found in CachingFilter:

/**
 * The cache holding the web pages. Ensure that all threads for a given cache name
 * are using the same instance of this.
 */
private BlockingCache blockingCache;

/**
 * Initialises blockingCache to use
 *
 * @throws CacheException The most likely cause is that a cache has not been
 *                        configured in Ehcache's configuration file ehcache.xml for the
 *                        filter name
 */
public void doInit() throws CacheException {
    synchronized (this.getClass()) {
        if (blockingCache == null) {
            final String cacheName = getCacheName();
            Ehcache cache = getCacheManager().getEhcache(cacheName);
            if (!(cache instanceof BlockingCache)) {
                //decorate and substitute
                BlockingCache newBlockingCache = new BlockingCache(cache);
                getCacheManager().replaceCacheWithDecoratedCache(cache, newBlockingCache);
            }
            blockingCache = (BlockingCache) getCacheManager().getEhcache(getCacheName());
        }
    }
}
Ehcache blockingCache = singletonManager.getEhcache("sampleCache1");

The returned cache will exhibit the decorations.

25.3 Built-in DecoratorsContents

25.3.1 BlockingCacheContents

A blocking decorator for an Ehcache, backed by a @link Ehcache.

It allows concurrent read access to elements already in the cache. If the element is null, other reads will block until an element with the same key is put into the cache.

This is useful for constructing read-through or self-populating caches.

BlockingCache is used by CachingFilter.

javadoc/net/sf/ehcache/constructs/blocking/BlockingCache

BlockingCache

25.3.2 SelfPopulatingCacheContents

A selfpopulating decorator for @link Ehcache that creates entries on demand.

Clients of the cache simply call it without needing knowledge of whether the entry exists in the cache. If null the entry is created.

The cache is designed to be refreshed. Refreshes operate on the backing cache, and do not degrade performance of get calls.

SelfPopulatingCache extends BlockingCache. Multiple threads attempting to access a null element will block until the first thread completes. If refresh is being called the threads do not block - they return the stale data.

This is very useful for engineering highly scalable systems.

javadoc/net/sf/ehcache/constructs/blocking/SelfPopulatingCache

SelfPopulatingCache

25.3.3 Caches with Exception HandlingContents

These are decorated. See Cache Exception Handlers for full details.

--- Hibernate Second Level Cache ---

26 Hibernate Second Level CacheContents

27 %toc|fromDepth=2|toDepth=2Contents

Ehcache easily integrates with the Hibernate Object/Relational persistence and query service. Gavin King, the maintainer of Hibernate, is also a committer to the Ehcache project. This ensures Ehcache will remain a first class cache for Hibernate.

Note these instructions are for Hibernate 3. Go to Guide for Version 1.1 for older instructions on how to use Hibernate 2.1.

The net.sf.ehcache.hibernate package provides classes integrating Ehcache with Hibernate.

27.1 DownloadContents

The Hibernate provider is in the ehcache-core module. Download here.

For a full distribution enabling connection to the Terracotta Server array download here.

27.2 Important Notice if Upgrading from Terracotta or Ehcache prior to 2.0Contents

New feature in Ehcache 2.0 Users of Ehcache and/or Terracotta Ehcache for Hibernate prior to Ehcache 2.0 should read Upgrade Notes for Ehcache versions prior to 2.0.

27.3 Quick StartContents

Follow these steps to get up and running quickly:

For more about cache configuration in Hibernate see the Hibernate documentation. Parts of this chapter are drawn from Hibernate documentation and source code comments.

They are reproduced here for convenience in using ehcache.

27.4 Setting Ehcache as the Hibernate Second Level CacheContents

To configure Ehcache as a Hibernate second level cache, set the region factory property (for Hibernate 3.3 and above) or the factory class property (Hibernate 3.2 and below) to one of the following in the Hibernate configuration.

Hibernate configuration is configured either via hibernate.cfg.xml, hibernate.properties or Spring. The format given is for hibernate.cfg.xml.

27.4.1 Hibernate 3.3 and higherContents

Use:

   <property name="hibernate.cache.region.factory_class">
        net.sf.ehcache.hibernate.EhCacheRegionFactory
   </property>

for instance creation, or

    <property name="hibernate.cache.region.factory_class">
        net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory
    </property>

to force Hibernate to use a singleton of Ehcache CacheManager.

27.4.2 Hibernate 3.0 - 3.2Contents

Use:

   <property name="hibernate.cache.provider_class">
       net.sf.ehcache.hibernate.EhCacheProvider
   </property>

for instance creation, or

   <property name="hibernate.cache.provider_class">
       net.sf.ehcache.hibernate.SingletonEhCacheProvider
   </property>

to force Hibernate to use a singleton Ehcache CacheManager.

27.4.3 Configuring the Ehcache Hibernate cachesContents

The configurationResourceName property is used to specify the location of the ehcache configuration file to be used with the given Hibernate instance and cache provider/region-factory.

hibernate.cache.region.factory_class=net.sf.ehcache.hibernate.EhCacheRegionFactory
net.sf.ehcache.configurationResourceName=/name_of_ehcache.xml

net.sf.ehcache.configurationResourceName - The name of a configuration resource to use.

The resource is searched for in the root of the classpath. It is needed to support multiple CacheManagers in the same VM. It tells Hibernate which configuration to use. An example might be "ehcache-2.xml".

When using multiple Hibernate instances it is therefore recommended to use multiple non-singleton providers or region factories, each with a dedicated Ehcache configuration resource.

27.4.4 Programmatic setting of the Hibernate Cache ProviderContents

The provider can also be set programmatically in Hibernate by adding necessary Hibernate property settings to the configuration before creating the SessionFactory: --- Configuration.setProperty("hibernate.cache.region.factory_class", "net.sf.ehcache.hibernate.EhCacheRegionFactory"). ---

27.5 Configuring Hibernate for CachingContents

In addition to configuring the Hibernate second level cache provider, Hibernate must also be told to enable caching for entities, collections, and queries.

For example to enable cache entries for the domain object com.somecompany.someproject.domain.Country there would be a mapping file something like the following:

<hibernate-mapping>

<class
    name="com.somecompany.someproject.domain.Country"
    table="ut_Countries"
    dynamic-update="false"
    dynamic-insert="false"
>
...
</class>
</hibernate-mapping>

To enable caching, add the following element.

<cache usage="read-write|nonstrict-read-write|read-only" />

e.g.

<hibernate-mapping>

<class
    name="com.somecompany.someproject.domain.Country"
    table="ut_Countries"
    dynamic-update="false"
    dynamic-insert="false"
>
  <cache usage="read-write" />
...
</class>
</hibernate-mapping>

This can also be achieved using the @Cache annotation, e.g.

@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Country { ... }

27.5.1 Definition of the different cache strategiesContents

27.5.1.1 read-only

Caches data that is never updated.

27.5.1.2 nonstrict-read-write

Caches data that is sometimes updated without ever locking the cache. If concurrent access to an item is possible, this concurrency strategy makes no guarantee that the item returned from the cache is the latest version available in the database. Configure your cache timeout accordingly!

27.5.1.3 read-write

Caches data that is sometimes updated while maintaining the semantics of "read committed" isolation level. If the database is set to "repeatable read", this concurrency strategy almost maintains the semantics. Repeatable read isolation is compromised in the case of concurrent writes.

27.6 Configuring ehcache.xmlContents

Because ehcache.xml has a defaultCache, caches will always be created when required by Hibernate. However more control can be exerted by specifying a configuration per cache, based on its name.

In particular, because Hibernate caches are populated from databases, there is potential for them to get very large. This can be controlled by capping their maxElementsInMemory and specifying whether to overflowToDisk beyond that.

Hibernate uses a specific convention for the naming of caches of Domain Objects, Collections, and Queries.

27.6.1 Domain ObjectsContents

Hibernate creates caches named after the fully qualified name of Domain Objects.

So, for example to create a cache for com.somecompany.someproject.domain.Country create a cache configuration entry similar to the following in ehcache.xml.

<cache
    name="com.somecompany.someproject.domain.Country"
    maxElementsInMemory="10000"
    eternal="false"
    timeToIdleSeconds="300"
    timeToLiveSeconds="600"
    overflowToDisk="true"
/>

27.6.2 HibernateContents

CacheConcurrencyStrategy read-write, nonstrict-read-write and read-only policies apply to Domain Objects.

27.6.3 CollectionsContents

Hibernate creates collection caches named after the fully qualified name of the Domain Object followed by "." followed by the collection field name.

For example, a Country domain object has a set of advancedSearchFacilities. The Hibernate doclet for the accessor looks like:

 /**
  * Returns the advanced search facilities that should appear for this country.
  * @hibernate.set cascade="all" inverse="true"
  * @hibernate.collection-key column="COUNTRY_ID"
  * @hibernate.collection-one-to-many class="com.wotif.jaguar.domain.AdvancedSearchFacility"
  * @hibernate.cache usage="read-write"
  */
 public Set getAdvancedSearchFacilities() {
    return advancedSearchFacilities;
 }

You need an additional cache configured for the set. The ehcache.xml configuration looks like:

<cache name="com.somecompany.someproject.domain.Country"
     maxElementsInMemory="50"
     eternal="false"
     timeToLiveSeconds="600"
     overflowToDisk="true"
 />
<cache
     name="com.somecompany.someproject.domain.Country.advancedSearchFacilities"
     maxElementsInMemory="450"
     eternal="false"
     timeToLiveSeconds="600"
     overflowToDisk="true"
 />

27.6.4 Hibernate CacheConcurrencyStrategyContents

read-write, nonstrict-read-write and read-only policies apply to Domain Object collections.

27.6.5 QueriesContents

Hibernate allows the caching of query results using two caches.

"net.sf.hibernate.cache.StandardQueryCache" and "net.sf.hibernate.cache.UpdateTimestampsCache" in versions 2.1 to 3.1 and "org.hibernate.cache.StandardQueryCache" and "org.hibernate.cache.UpdateTimestampsCache" in version 3.2. are always used.

27.6.6 StandardQueryCacheContents

This cache is used if you use a query cache without setting a name. A typical ehcache.xml configuration is:

<cache
    name="org.hibernate.cache.StandardQueryCache"
    maxElementsInMemory="5"
    eternal="false"
    timeToLiveSeconds="120"
    overflowToDisk="true"/>

27.6.7 UpdateTimestampsCacheContents

Tracks the timestamps of the most recent updates to particular tables. It is important that the cache timeout of the underlying cache implementation be set to a higher value than the timeouts of any of the query caches. In fact, it is recommend that the the underlying cache not be configured for expiry at all.

A typical ehcache.xml configuration is:

<cache
    name="org.hibernate.cache.UpdateTimestampsCache"
    maxElementsInMemory="5000"
    eternal="true"
    overflowToDisk="true"/>

27.6.8 Named Query CachesContents

In addition, a QueryCache can be given a specific name in Hibernate using Query.setCacheRegion(String name). The name of the cache in ehcache.xml is then the name given in that method. The name can be whatever you want, but by convention you should use "query." followed by a descriptive name.

E.g.

<cache name="query.AdministrativeAreasPerCountry"
    maxElementsInMemory="5"
    eternal="false"
    timeToLiveSeconds="86400"
    overflowToDisk="true"/>

27.6.9 Using Query CachesContents

For example, let's say we have a common query running against the Country Domain.

Code to use a query cache follows:

public List getStreetTypes(final Country country) throws HibernateException {
 final Session session = createSession();
 try {
        final Query query = session.createQuery(

        "select st.id, st.name"
        + " from StreetType st "
        + " where st.country.id = :countryId "
        + " order by st.sortOrder desc, st.name");
        query.setLong("countryId", country.getId().longValue());
        query.setCacheable(true);
        query.setCacheRegion("query.StreetTypes");
        return query.list();
     } finally {
        session.close();
     }
 }

The query.setCacheable(true) line caches the query.

The query.setCacheRegion("query.StreetTypes") line sets the name of the Query Cache.

Alex Miller has a good article on the query cache here.

27.6.10 Hibernate CacheConcurrencyStrategyContents

None of read-write, nonstrict-read-write and read-only policies apply to Domain Objects. Cache policies are not configurable for query cache. They act like a non-locking read only cache.

27.7 Demo AppsContents

We have demo applications showing how to use the Hibernate 3.3 CacheRegionFactory.

27.7.1 Hibernate TutorialContents

Check out from https://svn.terracotta.org/repo/forge/projects/hibernate-tutorial-web/trunk Terracotta Community Login Required

27.7.2 ExaminatorContents

Examinator is our complete application that shows many aspects of caching, all using the Terracotta Server Array.

Check out from https://svn.terracotta.org/svn/forge/projects/exam/ Terracotta Community Login Required

27.8 FAQContents

27.8.1 Should I use the provider in the Hibernate distribution or in Ehcache?Contents

Since Hibernate 2.1, Hibernate has included an Ehcache CacheProvider. That provider is periodically synced up with the provider in the Ehcache Core distribution. New features are generally added in to the Ehcache Core provider and then the Hibernate one.

27.8.2 What is the relationship between the Hibernate and Ehcache projects?Contents

Gavin King and Greg Luck cooperated to create Ehcache and include it in Hibernate. Since 2009 Greg Luck has been a committer on the Hibernate project so as to ensure Ehcache remains a first-class 2nd level cache for Hibernate.

27.8.3 Does Ehcache support the new Hibernate 3.3 2nd level caching SPI?Contents

Yes. Ehcache 2.0 supports this new API.

27.8.4 Does Ehcache support the transactional strategy?Contents

No. JTA support is new in Ehcache 2.0. We plan to add JTA support for Hibernate in an upcoming release at which time we will support this strategy. An exception will be thrown if this strategy is selected.

27.8.5 Is Ehcache Cluster Safe?Contents

hibernate.org maintains a table listing the providers. While ehcache works as a distributed cache for Hibernate, it is not listed as "Cluster Safe". What this means is that `Hibernate's lock and unlock methods are not implemented. Changes in one node will be applied without locking. This may or may not be a noticeable problem.

In Ehcache 1.7 when using Terracotta, this cannot happen as access to the clustered cache itself is controlled with read locks and write locks.

In Ehcache 2.0 when using Terracotta, the lock and unlock methods tie-in to the underlying clustered cache locks. We expect Ehcache 2.0 to be marked as cluster safe in new versions of the Hibernate documentation.

27.8.6 How are Hibernate Entities keyed?Contents

Hibernate identifies cached Entities via an object id. This is normally the primary key of a database row.

27.8.7 Can you use Identity mode with the Terracotta Server ArrayContents

You cannot use identity mode clustered cache with Hibernate. If the cache is exclusively used by Hibernate we will convert identity mode caches to serialization mode. If the cache cannot be determined to be exclusively used by Hibernate (i.e. generated from a singleton cache manager) then an exception will be thrown indicating the misconfigured cache. Serialization mode is in any case the default for Terracotta clustered caches.

27.8.8 I get org.hibernate.cache.ReadWriteCache - An item was expired by the cache while it was locked error messages. What is it?Contents

Soft locks are implemented by replacing a value with a special type that marks the element as locked, thus indicating to other threads to treat it differently to a normal element. This is used in the Hibernate Read/Write strategy to force fall-through to the database during the two-phase commit - since we don't know exactly what should be returned by the cache while the commit is in process (but the db does).

If a soft-locked Element is evicted by the cache during the 2 phase commit, then once the 2 phase commit completes the cache will fail to update (since the soft-locked Element was evicted) and the cache entry will be reloaded from the database on the next read of that object. This is obviously non-fatal (we're a cache failure here so it should not be a problem).

The only problem it really causes would I imagine be a small rise in db load.

So, in summary the Hibernate messages are not problematic.

The underlying cause is the probabilistic evictor can theoretically evict recently loaded items. This evictor has been tuned over successive ehcache releases. As a result this warning will happen most often in 1.6, less often in 1.7 and very rarely in 1.8.

You can also use the deterministic evictor to avoid this problem. Specify the java -Dnet.sf.ehcache.use.classic.lru=true system property to turn on classic LRU which contains a deterministic evictor.

27.9 Performance TipsContents

27.9.1 Session.loadContents

Session.load will always try to use the cache.

27.9.2 Session.find and Query.findContents

Session.find does not use the cache for the primary object. Hibernate will try to use the cache for any associated objects. Session.find does however cause the cache to be populated.

Query.find works in exactly the same way.

Use these where the chance of getting a cache hit is low.

27.9.3 Session.iterate and Query.iterateContents

Session.iterate always uses the cache for the primary object and any associated objects.

Query.iterate works in exactly the same way.

Use these where the chance of getting a cache hit is high.

27.10 How to ScaleContents

Configuring each Hibernate instance with a standalone ehcache will dramatically improve performance. However most production applications use multiple application instances for redundancy and for scalability. Ideally applications are horizontally scalable, where adding more application instances linearly improves throughput.

With an application deployed on multiple nodes, using standalone Ehcache means that each instance holds its own data. On a cache miss on any node, Hibernate will hit the database. As each new node gets added database workload goes up. The solution is to turn on distributed caching.

Ehcache comes with replicated caching via RMI, JGroups or JMS. These replicate without locking and are suitable for database offload. Generally session.refresh() should be used to check the cache against the database before performing a write that must be correct. Secondly, as each node stores all data, the cache size is limited to a comfortable storage size. Memory size is usually limited by garbage collection. Disk can also be used, but the graphs are serialized which adds overhead and results in duplication in the deserialized object graphs.

Ehcache is also the caching API to the Terracotta Server Array. Reads and writes use cluster wide locks, so when using read write Hibernate caches, the cache data on all nodes will be correct, and it is not necessary to call session.refresh().

Ehcache EX, using a single or redundant Terracotta Server Array server can comfortably store approximately 20GB per stripe. The maxElementsInMemory cache setting is used to apportion a percentage of that in process for added performance, it does not limit the size. Using striping which comes with Ehcache FX, terabyte sized caches are possible. It is possible to cache the entire database with a resulting large database offload.

These scaling decisions can be deferred. The plugin is the same regardless of how it is configured. The optimal deployment can thus be determined during performance testing or based on production experience. Finally a new application can scale as it's use grows without expensive re-architecting.

--- Shutting Down Ehcache ---

28 Shutting Down EhcacheContents

If you are using persistent disk stores, or distributed caching, care should be taken to shutdown ehcache.

Note that Hibernate automatically shuts down its Ehcache CacheManager.

The recommended way to shutdown the Ehcache is:

28.1 ServletContextListenerContents

Ehcache proivdes a ServletContextListener that shutsdown CacheManager. Use this when you want to shutdown Ehcache automatically when the web application is shutdown.

To receive notification events, this class must be configured in the deployment descriptor for the web application.

To do so, add the following to web.xml in your web application:

     <listener>
          <listener-class>net.sf.ehcache.constructs.web.ShutdownListener</listener-class>
     </listener>

28.2 The Shutdown HookContents

Ehcache CacheManager can optionally register a shutdown hook.

To do so, set the system property net.sf.ehcache.enableShutdownHook=true.

This will shutdown the CacheManager when it detects the Virtual Machine shutting down and it is not already shut down.

28.2.1 When to use the shutdown hookContents

Use the shutdown hook where:

28.2.2 What the shutdown hook doesContents

The shutdown hook is on CacheManager. It simply calls the shutdown method.

The sequence of events is:

28.2.3 When a shutdown hook will run, and when it will notContents

The shutdown hook runs when:

The shutdown hook will not run when:

28.3 Dirty ShutdownContents

If Ehcache is shutdown dirty then any persistent disk stores will be corrupted. They will be deleted, with a log message, on the next startup.

Replications waiting to happen to other nodes in a distributed cache will also not get written.

--- Web Caching ---

29 Web CachingContents

Ehcache provides a set of general purpose web caching filters in the ehcache-web module.

Using these can make an amazing difference to web application performance. A typical server can deliver 5000+ pages per second from the page cache. With built-in gzipping, storage and network transmission is highly efficient. Cache pages and fragments make excellent candidates for DiskStore storage, because the object graphs are simple and the largest part is already a byte[].

29.1 SimplePageCachingFilterContents

This is a simple caching filter suitable for caching compressable HTTP responses such as HTML, XML or JSON.

It uses a Singleton CacheManager created with the default factory method. Override to use a different CacheManager

It is suitable for:

29.2 KeysContents

Pages are cached based on their key. The key for this cache is the URI followed by the query string. An example is /admin/SomePage.jsp?id=1234&name=Beagle.

This key technique is suitable for a wide range of uses. It is independent of hostname and port number, so will work well in situations where there are multiple domains which get the same content, or where users access based on different port numbers.

A problem can occur with tracking software, where unique ids are inserted into request query strings. Because each request generates a unique key, there will never be a cache hit. For these situations it is better to parse the request parameters and override calculateKey(javax.servlet.http.HttpServletRequest) with an implementation that takes account of only the significant ones.

29.3 Configuring the cacheNameContents

A cache entry in ehcache.xml should be configured with the name of the filter.

Names can be set using the init-param codecacheName/code, or by sub-classing this class and overriding the name.

29.4 Concurent Cache MissesContents

A cache miss will cause the filter chain, upstream of the caching filter to be processed. To avoid threads requesting the same key to do useless duplicate work, these threads block behind the first thread.

The thead timeout can be set to fail after a certain wait by setting the init-param codeblockingTimeoutMillis/code. By default threads wait indefinitely. In the event upstream processing never returns, eventually the web server may get overwhelmed with connections it has not responded to. By setting a timeout, the waiting threads will only block for the set time, and then throw a @link net.sf.ehcache.constructs.blocking.LockTimeoutException. Under either scenario an upstream failure will still cause a failure.

29.5 GzippingContents

Significant network efficiencies, and page loading speedups, can be gained by gzipping responses.

Whether a response can be gzipped depends on:

29.6 Caching HeadersContents

The SimpleCachingHeadersPageCachingFilter extends SimplePageCachingFilter to provide the HTTP cache headers: ETag, Last-Modified and Expires. It supports conditional GET.

Because browsers and other HTTP clients have the expiry information returned in the response headers, they do not even need to request the page again. Even once the local browser copy has expired, the browser will do a conditional GET.

So why would you ever want to use SimplePageCachingFilter, which does not set these headers? The answer is that in some caching scenarios you may wish to remove a page before its natural expiry. Consider a scenario where a web page shows dynamic data. Under Ehcache the Element can be removed at any time. However if a browser is holding expiry information, those browsers will have to wait until the expiry time before getting updated. The caching in this scenario is more about defraying server load rather than minimising browser calls.

29.7 Init-ParamsContents

The following init-params are supported:

29.8 ReentranceContents

Care should be taken not to define a filter chain such that the same CachingFilter class is reentered. The CachingFilter uses the BlockingCache. It blocks until the thread which did a get which results in a null does a put. If reentry happens a second get happens before the first put. The second get could wait indefinitely. This situation is monitored and if it happens, an IllegalStateException will be thrown.

29.9 SimplePageFragmentCachingFilterContents

The SimplePageFragmentCachingFilter does everyting that SimplePageCachingFilter does, except it never gzips, so the fragments can be combined. There is variant of this filter which sets browser caching headers, because that is only applicable to the entire page.

29.10 Example web.xml configurationContents

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd "
     version="2.5">

  <filter>
    <filter-name>CachePage1CachingFilter</filter-name>
    <filter-class>net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter
    </filter-class>
    <init-param>
      <param-name>suppressStackTraces</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>cacheName</param-name>
      <param-value>CachePage1CachingFilter</param-value>
    </init-param>
  </filter>

  <filter>
    <filter-name>SimplePageFragmentCachingFilter</filter-name>
    <filter-class>net.sf.ehcache.constructs.web.filter.SimplePageFragmentCachingFilter
    </filter-class>
    <init-param>
      <param-name>suppressStackTraces</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>cacheName</param-name>
      <param-value>SimplePageFragmentCachingFilter</param-value>
    </init-param>
  </filter>

  <filter>
    <filter-name>SimpleCachingHeadersPageCachingFilter</filter-name>
    <filter-class>net.sf.ehcache.constructs.web.filter.SimpleCachingHeadersPageCachingFilter
    </filter-class>
    <init-param>
      <param-name>suppressStackTraces</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>cacheName</param-name>
      <param-value>CachedPage2Cache</param-value>
    </init-param>

  </filter>

  <!-- This is a filter chain. They are executed in the order below.
  Do not change the order. -->
  <filter-mapping>
    <filter-name>CachePage1CachingFilter</filter-name>
    <url-pattern>/CachedPage.jsp</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>FORWARD</dispatcher>
  </filter-mapping>

  <filter-mapping>
    <filter-name>SimplePageFragmentCachingFilter</filter-name>
    <url-pattern>/include/Footer.jsp</url-pattern>
  </filter-mapping>

  <filter-mapping>
    <filter-name>SimplePageFragmentCachingFilter</filter-name>
    <url-pattern>/fragment/CachedFragment.jsp</url-pattern>
  </filter-mapping>

  <filter-mapping>
    <filter-name>SimpleCachingHeadersPageCachingFilter</filter-name>
    <url-pattern>/CachedPage2.jsp</url-pattern>
  </filter-mapping>

An ehcache.xml configuration file, matching the above would then be:

<Ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="../../main/config/ehcache.xsd">

    <diskStore path="java.io.tmpdir"/>


    <defaultCache
            maxElementsInMemory="10"
            eternal="false"
            timeToIdleSeconds="5"
            timeToLiveSeconds="10"
            overflowToDisk="true"
            />



    <!-- Page and Page Fragment Caches -->

    <cache name="CachePage1CachingFilter"
           maxElementsInMemory="10"
           eternal="false"
           timeToIdleSeconds="10000"
           timeToLiveSeconds="10000"
           overflowToDisk="true">
    </cache>

    <cache name="CachedPage2Cache"
           maxElementsInMemory="10"
           eternal="false"
           timeToLiveSeconds="3600"
           overflowToDisk="true">
    </cache>

    <cache name="SimplePageFragmentCachingFilter"
           maxElementsInMemory="10"
           eternal="false"
           timeToIdleSeconds="10000"
           timeToLiveSeconds="10000"
           overflowToDisk="true">
    </cache>

    <cache name="SimpleCachingHeadersTimeoutPageCachingFilter"
           maxElementsInMemory="10"
           eternal="false"
           timeToIdleSeconds="10000"
           timeToLiveSeconds="10000"
           overflowToDisk="true">
    </cache>

</ehcache>

29.11 CachingFilter ExceptionsContents

Additional exception types have been added to the Caching Filter.

29.11.1 FilterNonReentrantExceptionContents

Thrown when it is detected that a caching filter's doFilter method is reentered by the same thread. Reentrant calls will block indefinitely because the first request has not yet unblocked the cache. Nasty.

29.11.2 AlreadyGzippedExceptionContents

The web package performs gzipping operations. One cause of problems on web browsers is getting content that is double or triple gzipped. They will either get gobblydeegook or a blank page. This exception is thrown when a gzip is attempted on already gzipped content.

29.11.3 ResponseHeadersNotModifiableExceptionContents

A gzip encoding header needs to be added for gzipped content. The HttpServletResponse#setHeader() method is used for that purpose. If the header had already been set, the new value normally overwrites the previous one. In some cases according to the servlet specification, setHeader silently fails. Two scenarios where this happens are:

30 Distributed Caching OptionsContents

Ehcache provides a pluggable distributed caching mechanism. This enables for multiple CacheManagers and their caches in multiple JVMs to share data with each other.

30.1 Pluggable MechanismsContents

Ehcache has a pluggable cache replication scheme which enables the addition of cache replication mechanisms.

The following distribution mechanisms are supported in Ehcache 1.7:

Each of the is covered in its own chapter.

30.2 The need for shared cache dataContents

Many production applications are deployed in clusters. If each application maintains its own cache, then updates made to one cache will not appear in the others. A workaround for web based applications is to use sticky sessions, so that a user, having established a session on one server, stays on that server for the rest of the session. A workaround for transaction processing systems using Hibernate is to do a session.refresh on each persistent object as part of the save. session.refresh explicitly reloads the object from the database, ignoring any cache values.

30.3 Replicated CachesContents

One solution is to replicate data between the caches to keep them consistent, or coherent. Typical operations which Applicable operations include:

Update supports updateViaCopy or updateViaInvalidate. The latter sends the a remove message out to the cache cluster, so that other caches remove the Element, thus preserving coherency. It is typically a lower cost option than a copy.

30.4 Using a Cache ServerContents

Ehcache 1.5 supports the Ehcache Cache Server.

To achieve shared data, all JVMs read to and write from a Cache Server, which runs it in its own JVM.

To achieve redundancy, the Ehcache inside the Cache Server can be set up in its own cluster.

This technique will be expanded upon in Ehcache 1.6.

30.5 Notification StrategiesContents

The best way of notifying of put and update depends on the nature of the cache.

If the Element is not available anywhere else then the Element itself should form the payload of the notification. An example is a cached web page. This notification strategy is called copy.

Where the cached data is available in a database, there are two choices. Copy as before, or invalidate the data. By invalidating the data, the application tied to the other cache instance will be forced to refresh its cache from the database, preserving cache coherency. Only the Element key needs to be passed over the network.

Ehcache supports notification through copy and invalidate, selectable per cache.

30.6 Potential Issues with Distributed CachingContents

30.6.1 Potential for Inconsistent DataContents

Timing scenarios, race conditions, delivery, reliability constraints and concurrent updates to the same cached data can cause inconsistency (and thus a lack of coherency) across the cache instances.

This potential exists within the Ehcache implementation. These issues are the same as what is seen when two completely separate systems are sharing a database; a common scenario.

Whether data inconsistency is a problem depends on the data and how it is used. For those times when it is important, Ehcache provides for synchronous delivery of puts and updates via invalidation. These are discussed below:

30.6.1.1 Synchronous Delivery

Delivery can be specified to be synchronous or asynchronous. Asynchronous delivery gives faster returns to operations on the local cache and is usually preferred. Synchronous delivery adds time to the local operation, however delivery of an update to all peers in the cluster happens before the cache operation returns.

30.6.1.2 Put and Update via Invalidation

The default is to update other caches by copying the new value to them. If the replicatePutsViaCopy property is set to false in the replication configuration, puts are made by removing the element in any other cache peers. If the replicateUpdatesViaCopy property is set to false in the replication configuration, updates are made by removing the element in any other cache peers.

This forces the applications using the cache peers to return to a canonical source for the data.

A similar effect can be obtained by setting the element TTL to a low value such as a second.

Note that these features impact cache performance and should not be used where the main purpose of a cache is performance boosting over coherency.

30.6.2 Use of Time To IdleContents

Time To Idle is inconsistent with distributed caching. Time-to-idle makes some entries live longer on some nodes than in others because of cache usage patterns. However, the cache entry "last touched" timestamp is not replicated across the distributed cache.

Do not use Time To Idle with distributed caching, unless you do not care about inconsistent data across nodes.

--- Distributed Caching Using Terracotta Server Array ---

31 Distributed Caching Using Terracotta Server ArrayContents

Terracotta has been integrated with Ehcache since Ehcache 1.4.

From version 1.7 Ehcache has been seamlessly integrated with Terracotta 3.1.1 and takes just a few lines of config in ehcache.xml to get up and running.

New feature in Ehcache 2.0 In Ehcache 2.0 additional configuration options have been added which provide finer grained control.

Distribution with the Terracotta Server Array ("TSA") is the preferred distribution mechanism. It provides coherency, JTA, HA, scale and high performance. It is available as open source or with additional features in the Ehcache EX and FX product editions.

31.1 ArchitectureContents

Ehcache distributed with TSA is different to the other distribution mechanisms. They all replicate data, with 100% of data held in each node. Scaling is thus limited to how much can be comfortably held in each node. Replication is also not JTA transactional or guaranteed coherent.

With TSA the data is split between an Ehcache node, which is the L1 Cache and the TSA, which is the L2 Cache. As with the other replication mechanisms the L1 can hold as much data as is comfortable. All the rest lies in the L2. In Ehcache EX, each CacheManager can have only one logical TSA (there can be multiple redundant TSAs for HA). In Ehcache FX, the TSAs are striped for unlimited scale.

Data is held in-process in the Ehcache L1 for rapid access, however the data is also always in the TSA. So the cache is unaffected by termination of an Ehcache node. When the node comes back up it reconnects to the TSA L2 and as it uses data fills its local L1. There is thus no notion of a bootstrap as there is with the other distribution mechanisms.

31.2 Worked ExampleContents

As this example shows, running Ehcache with Terracotta clustering is no different from normal programmatic use.

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

public class TerracottaExample {
    CacheManager cacheManager = new CacheManager();

    public TerracottaExample() {
        Cache cache = cacheManager.getCache("sampleTerracottaCache");
        int cacheSize = cache.getKeys().size();
        cache.put(new Element("" + cacheSize, cacheSize));
        for (Object key : cache.getKeys()) {
            System.out.println("Key:" + key);
        }
    }

    public static void main(String[] args) throws Exception {
        new TerracottaExample();
    }
}

The above example looks for sampleTerracottaCache.

In ehcache.xml, we need to uncomment or add the following line:

    <terracottaConfig url="localhost:9510"/>

which tells Ehcache to load the Terracotta server config from localhost port 9510. Note: You must have a Terracotta 3.1.1 or higher server running locally for this example.

Next we want to enable Terracotta clustering for the cache named sampleTerracottaCache. Uncomment or add the following in ehcache.xml.

   <cache name="sampleTerracottaCache"
          maxElementsInMemory="1000"
          eternal="false"
          timeToIdleSeconds="3600"
          timeToLiveSeconds="1800"
          overflowToDisk="false">
       <terracotta/>
   </cache>

That's it!

31.3 Terracotta ConfigurationContents

Terracotta configuration in ehcache.xml is in three parts:

31.3.1 CacheManager ConfigurationContents

The attributes of ehcache are:

31.3.2 Terracotta Server ConfigurationContents

Note: You need to install and run one or more Terracotta servers to use Terracotta clustering.

See http://www.terracotta.org/web/display/orgsite/Download.

With a server/servers up and running you need to specify the location of the servers.

Configuration can be specified in two main ways: by reference to a source of configuration or by use of an embedded Terracotta configuration file.

31.3.2.1 Specification of a source of configuration

To specify a reference to a source (or sources) of configuration, use the url attribute. The url attribute must contain a comma-separated list of:

31.3.2.2 Specification using embedded tc-config

To embed a Terracotta configuration file within the Ehcache configuration, simply place the usual Terracotta XML config within the terracottaConfig element.

In this example we have two Terracotta servers running on server1 and server2.

    <terracottaConfig>
        <tc-config>
            <servers>
                <server host="server1" name="s1"/>
                <server host="server2" name="s2"/>
            </servers>
            <clients>
                <logs>app/logs-%i</logs>
            </clients>
        </tc-config>
    </terracottaConfig>

31.3.3 Enabling Terracotta clustering per cacheContents

Cache elements can also contain information about whether the cache can be clustered with Terracotta.

The terracotta sub-element has the following attributes:

31.4 Copy On ReadContents

The copyOnRead setting is most easily explained by first examining what it does when not enabled and exploring the potential problems that can arise.

For a cache for which copyOnRead is NOT enabled, the following reference comparsion will always be true (NOTE: assuming no other thread changes the cache mapping between the get()'s)

    Object obj1 = c.get("key").getValue();
    Object obj2 = c.get("key").getValue();

    if (obj1 == obj2) {
      System.err.println("Same value objects!");
    }

The fact that the same object reference is returned accross multiple get()'s implies that the cache is storing a direct reference to cache value. When copyOnRead is enabled the object references will be fresh and unique upon every get().

This default behavior (copyOnRead=false) is usually what you want although there are at least two scenarios in which this is problematic: (1) Caches shared between classloaders and (2) Mutable value objects

Imagine two web applications that both have access to the same Cache instance (this implies that the core ehcache classes are in a common classloader). Imagine further that the classes for value types in the cache are duplicated in the web application (ie. they are not present in the common loader). In this scenario you would get ClassCastExceptions when one web application accessed a value previously read by the other application. One solution to this problem is obviously to move the value types to the common loader, but another is to enable copyOnRead so that thread context loader of the caller will be used to materialize the cache values on each get(). This feature has utility in OSGi environments as well where a common cache service might be shared between bundles

Another subtle issue concerns mutable value objects in a clustered cache. Consider this simple code which shows a Cache that contains a mutable value type (Foo):

    class Foo {
      int field;
    }

    Foo foo = (Foo) c.get("key").getValue();
    foo.field++;

    // foo instance is never re-put() to the cache

    // ...

If the Foo instance is never re-put() to the Cache your local cache is no longer consistent with the cluster (it is locally modified only). Enabling copyOnRead eliminates this possibility since the only way to affect cache values is to call mutator methods on the Cache.

It is worth noting that there is a performance penalty to copyOnRead since values are deserialized on every get().

31.5 Behaviour differences with CacheEventListeners when using Terracotta ClusteringContents

Terracotta clustering works by clustering the MemoryStore, unlike the replication mechanisms which use the CacheEventListener infrastructure.

This results in a simpler programming contract than with the replication mechanisms.

Things to note:

31.5.1 Cache listenersContents

Cache listeners listen for changes, including replicated cluster changes, made through the Cache API. Because Terracotta cluster changes happen transparently directly to the MemoryStore a listener will not be invoked when an event occurs out on the cluster. If it occurs locally, then it must have occurred through the Cache API, so a local event will be detected by a local listener.

A common use of listeners is to trigger a reload of a just invalidated Element. In Terracotta clustering this is avoided as a change in one node is always coherent to the other nodes.

To send out cache change events across the cluster, you need to set up a local listener on the relevant cache so that these events can be propagated to other nodes. This is done by adding the following cacheEventListenerFactory tag to the cache:

    <cacheEventListenerFactory class="net.sf.ehcache.event.TerracottaCacheEventReplicationFactory"/>

31.5.2 Overflow to DiskContents

Overflow to Disk is ignored when using Terracotta Clustering. However it is not needed because the Terracotta server has its own overflow to disk. Once the maxElementsInMemory limit is reached Elements will be evicted to the cluster.

31.6 Cluster Topology New feature in Ehcache 2.0Contents

The interface net.sf.ehcache.cluster.CacheCluster provides methods for obtaining topology information for a Terracotta cluster.

The following methods are available:

31.7 Terracotta Cluster Events New feature in Ehcache 2.0Contents

Terracotta has a Terracotta Cluster event notification mechanism. From Ehcache 2.0, Ehcache can receive these events.

This is not cache event notification, rather it is cluster event notification.

The Terracotta Distributed Ehcache cluster events API provides access to Terracotta cluster events and cluster topology.

The interface net.sf.ehcache.cluster.ClusterTopologyListener provides methods for detecting the following cluster events:

public interface ClusterTopologyListener {

    /**
     * A node has joined the cluster
     *
     * @param node The joining node
     */
    void nodeJoined(ClusterNode node);

    /**
     * A node has left the cluster
     *
     * @param node The departing node
     */
    void nodeLeft(ClusterNode node);

    /**
     * This node has established contact with the cluster and can execute clustered operations.
     *
     * @param node The current node
     */
    void clusterOnline(ClusterNode node);

    /**
     * This node has lost contact (possibly temporarily) with the cluster and cannot execute
     * clustered operations
     *
     * @param node The current node
     */
    void clusterOffline(ClusterNode node);

}

31.7.1 Example CodeContents

This example prints out the cluster nodes and then registers a ClusterTopologyListener which prints out events as they happen.

    CacheManager mgr = ...

    CacheCluster cluster = mgr.getCluster("Terracotta");



    // Get current nodes

    Collection<ClusterNode> nodes = cluster.getNodes();

    for(ClusterNode node : nodes) {

      System.out.println(node.getId() + " " + node.getHostname() + " " + node.getIp());

    }



    // Register listener

    cluster.addTopologyListener(new ClusterTopologyListener() {

      public void nodeJoined(ClusterNode node) { System.out.println(node + " joined"); }

      public void nodeLeft(ClusterNode node) { System.out.println(node + " left"); }

      public void clusterOnline(ClusterNode node) { System.out.println(node + " enabled"); }

      public void clusterOffline(ClusterNode node) { System.out.println(node + " disabled"); }

    });

31.7.2 Uses for Cluster EventsContents

If Ehcache got disconnected from the Terracotta Server Array say due to a network issue, then in Ehcache 2.0 each cache operation will block indefinitely. In other words it is configured for fail-fast to protect the ACIDity of the cluster.

However this approach will also cause processing of requests to the cache to stop likely causing the outage to cascade. In some cases graceful degradation may be more appropriate. When the clusterOffline events fires you could call Cache.setDisabled() which will cause puts and gets to bypass the cache. Your application would then degrade to operating without a cache, but might be able to do useful work.

You could also take the whole application off-line.

When connectivity is restored you could then reverse the action, taking the cache back online or the application back on line as the case may be.

We expect to add some of these common behaviours into configuration in the next release:

31.8 More InformationContents

Please see Terracotta Documentation for much more information.

31.9 FAQContents

31.9.1 Is Expiry the same in Terracotta?Contents

timeToIdle and timeToLive work as usual. Ehcache 1.7 introduced a less fine grained age recording in Element which rounds up to the nearest second. Some APIs may be sensitive to this change.

In Ehcache Elements can have overridden TTI and TTLs. Terracotta supports this functionality.

31.9.2 What Eviction strategies are supported?Contents

Ehcache supports LRU, LFU and FIFO eviction strategies.

Terracotta supports LRU and LFU eviction from the local node. Not FIFO and not custom evictors.

31.9.3 What Stores are available and how are they configured?Contents

The Terracotta server provides an additional store, generally referred to as the Level 2 or L2 store.

The MemoryStore in JVM in the local node is referred to as the L1 Store.

maxElementsInMemory - the maximum number of elements in the local L1 store.

maxElementsOnDisk - is overridden when using Terracotta to provide the L2 size. The L2 size is effectively the maximum cache size.

overflowToDisk normally controls whether to overflow to the DiskStore. This is ignored when using Terracotta - the DiskStore is never used. When the store gets full, elements will always overflow to the Terracotta L2 Store running on the server. The L2 can be further configured with the tcconfig.

31.9.4 When do Elements overflow?Contents

Two things to cause elements to be flushed from L1 to L2.

31.9.5 How does Element equality work in Serialization mode?Contents

An Element, key and value in Ehcache is guaranteed to .equals() another as it moves between stores.

In the Express install or Serialization mode of Terracotta, which is the default, Terracotta is the same. Elements will not == each other as they move between stores.

31.9.6 How does Element equality work in Identity mode?Contents

An Element in Ehcache is guaranteed to .equals() another as it moves between stores.

However in Identity mode, Terracotta makes a further guarantee that they key and the value ==. This is achieved using extensions to the Java Memory Model.

31.9.7 What is the recommended way to write to a database?Contents

Terracotta' non Ehcache API offers an async writethrough to the database which is guaranteed. It uses the TIM Async module and works by putting the database update in a clustered queue. It guarantees that a node, even if the local node fails, will take it out and process it.

That option is not available with Ehcache although it may get added.

31.9.8 If updates to a database bypass the Terracotta clustered application, then how is that coherent?Contents

It isn't. This is a problem with using a database as an integration point. Integration via a message queue, with a Terracotta clustered application acting as a message queue listener and updating the database avoids this. As would The application receiving a REST or SOAP call and writing to the database.

AQ can have DB trigger put in a poll. Or AQ can push it up.

31.9.9 Do CacheEventListeners work?Contents

A local CacheEventListener will work locally, but other nodes in a Terracotta cluster are not notified unless the TerracottaCacheEventReplicationFactory event listener is registered for the cache.

31.9.10 What are the JMX statistics available in the Terracotta Developer Console?Contents

SampledCache and SampledCacheManager MBeans are made available in the Terracotta Developer Console.

These are time based gauges, based on once per second measurements. These are different to the JMX MBeans available through the ManagementService.

31.9.11 What classloader is used to deserialize clustered objects in valueMode="serialization"?Contents

The following classloaders are tried in this order:

31.9.12 What versions of Ehcache and Terracotta work together?Contents

For full compatibility Ehcache 2.0 should be used with Terracotta Server 3.2.1.

Ehcache 1.7 works with TC 3.1.1.

Ehcache Core 1.7.3 core works with TC 3.2.

31.9.13 What happens when an L1 (i.e. an Ehcache node) disconnects from the L2 (i.e. the Terracotta Server Array)?Contents

32 RMI Distributed CachingContents

images/rmi_replication

Since version 1.2, Ehcache has provided distributed caching using RMI.

An RMI implementation is desirable because:

While RMI is a point-to-point protocol, which can generate a lot of network traffic, Ehcache manages this through batching of communications for the asynchronous replicator.

To set up RMI distributed caching you need to configure the CacheManager with:

32.1 Suitable Element TypesContents

Only Serializable Elements are suitable for replication.

Some operations, such as remove, work off Element keys rather than the full Element itself. In this case the operation will be replicated provided the key is Serializable, even if the Element is not.

32.2 Configuring the Peer ProviderContents

32.2.1 Peer DiscoveryContents

Ehcache has the notion of a group of caches acting as a distributed cache. Each of the caches is a peer to the others. There is no master cache. How do you know about the other caches that are in your cluster? This problem can be given the name Peer Discovery.

Ehcache provides two mechanisms for peer discovery, just like a car: manual and automatic.

To use one of the built-in peer discovery mechanisms specify the class attribute of cacheManagerPeerProviderFactory as net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory in the ehcache.xml configuration file.

32.2.2 Automatic Peer DiscoveryContents

Automatic discovery uses TCP multicast to establish and maintain a multicast group. It features minimal configuration and automatic addition to and deletion of members from the group. No a priori knowledge of the servers in the cluster is required. This is recommended as the default option.

Peers send heartbeats to the group once per second. If a peer has not been heard of for 5 seconds it is dropped from the group. If a new peer starts sending heartbeats it is admitted to the group.

Any cache within the configuration set up as replicated will be made available for discovery by other peers.

To set automatic peer discovery, specify the properties attribute of cacheManagerPeerProviderFactory as follows:

peerDiscovery=automatic multicastGroupAddress=multicast address | multicast host name multicastGroupPort=port timeToLive=0-255 (See below in common problems before setting this) hostName= the hostname or IP of the interface to be used for sending and receiving multicast packets (relevant to mulithomed hosts only)

32.2.2.1 Example

Suppose you have two servers in a cluster. You wish to distribute sampleCache11 and sampleCache12. The configuration required for each server is identical:

Configuration for server1 and server2

 <cacheManagerPeerProviderFactory
 class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"

 properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
 multicastGroupPort=4446, timeToLive=32"/>

32.2.3 Manual Peer DiscoveryContents

Manual peer configuration requires the IP address and port of each listener to be known. Peers cannot be added or removed at runtime. Manual peer discovery is recommended where there are technical difficulties using multicast, such as a router between servers in a cluster that does not propagate multicast datagrams. You can also use it to set up one way replications of data, by having server2 know about server1 but not vice versa.

To set manual peer discovery, specify the properties attribute of cacheManagerPeerProviderFactory as follows: peerDiscovery=manual rmiUrls=//server:port/cacheName, ...

The rmiUrls is a list of the cache peers of the server being configured. Do not include the server being configured in the list.

32.2.3.1 Example

Suppose you have two servers in a cluster. You wish to distribute sampleCache11 and sampleCache12. Following is the configuration required for each server:

Configuration for server1

 <cacheManagerPeerProviderFactory
 class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"

 properties="peerDiscovery=manual,
 rmiUrls=//server2:40001/sampleCache11|//server2:40001/sampleCache12"/>

Configuration for server2

 <cacheManagerPeerProviderFactory
 class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"

 properties="peerDiscovery=manual,
 rmiUrls=//server1:40001/sampleCache11|//server1:40001/sampleCache12"/>

32.3 Configuring the CacheManagerPeerListenerContents

A CacheManagerPeerListener listens for messages from peers to the current CacheManager.

You configure the CacheManagerPeerListener by specifiying a CacheManagerPeerListenerFactory which is used to create the CacheManagerPeerListener using the plugin mechanism.

The attributes of cacheManagerPeerListenerFactory are:

32.4 Configuring Cache ReplicatorsContents

Each cache that will be distributed needs to set a cache event listener which then replicates messages to the other CacheManager peers. This is done by adding a cacheEventListenerFactory element to each cache's configuration.

<!-- Sample cache named sampleCache2. -->
<cache name="sampleCache2"
   maxElementsInMemory="10"
   eternal="false"
   timeToIdleSeconds="100"
   timeToLiveSeconds="100"
   overflowToDisk="false">
 <cacheEventListenerFactory
    class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
    properties="replicateAsynchronously=true, replicatePuts=true, replicateUpdates=true,
    replicateUpdatesViaCopy=false, replicateRemovals=true "/>
</cache>

class - use net.sf.ehcache.distribution.RMICacheReplicatorFactory

The factory recognises the following properties:

To reduce typing if you want default behaviour, which is replicate everything in asynchronous mode, you can leave off the RMICacheReplicatorFactory properties as per the following example:

    <!-- Sample cache named sampleCache4. All missing RMICacheReplicatorFactory properties
         default to true -->
    <cache name="sampleCache4"
           maxElementsInMemory="10"
           eternal="true"
           overflowToDisk="false"
           memoryStoreEvictionPolicy="LFU">
        <cacheEventListenerFactory
            class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
    </cache>

32.5 Configuring Bootstrap from a Cache PeerContents

When a peer comes up, it will be incoherent with other caches. When the bootstrap completes it will be partially coherent. Bootstrap gets the list of keys from a random peer, and then loads those in batches from random peers. If bootstrap fails then the Cache will not start (not like this right now). However if a distributed cache operation occurs which is then overwritten by bootstrap there is a chance that the cache could be inconsistent.

Here are some scenarios:

Delete overwritten by boostrap put --- Cache A keys with values: 1, 2, 3, 4, 5

Cache B starts bootstrap

Cache A removes key 2

Cache B removes key 2 and then bootstrap puts it back

---

Put overwritten by boostrap put --- Cache A keys with values: 1, 2, 3, 4, 5

Cache B starts bootstrap

Cache A updates the value of key 2

Cache B updates the value of key 2 and then bootstrap overwrites it with the old value

---

The solution is for bootstrap to get a list of keys and write them all before committing transactions.

This could cause synchronous transaction replicates to back up. To solve this problem, commits will be accepted, but not written to the cache until after bootstrap. Coherency is maintained because the cache is not available until bootstrap has completed and the transactions have been completed.

32.6 Full ExampleContents

Ehcache's own integration tests provide complete examples of RMI-based replication. The best example is the integration test for cache replication. You can see it online here: http://ehcache.org/xref-test/net/sf/ehcache/distribution/RMICacheReplicatorTest.html

The test uses 5 ehcache.xml's representing 5 CacheManagers set up to distribute using RMI.

32.7 Common ProblemsContents

32.7.1 Tomcat on WindowsContents

There is a bug in Tomcat and/or the JDK where any RMI listener will fail to start on Tomcat if the installation path has spaces in it. See http://archives.java.sun.com/cgi-bin/wa?A2=ind0205&L=rmi-users&P=797 and http://www.ontotext.com/kim/doc/sys-doc/faq-howto-bugs/known-bugs.html.

As the default on Windows is to install Tomcat in "Program Files", this issue will occur by default.

32.7.2 Multicast BlockingContents

The automatic peer discovery process relies on multicast. Multicast can be blocked by routers. Virtualisation technologies like Xen and VMWare may be blocking multicast. If so enable it. You may also need to turn it on in the configuration for your network interface card.

An easy way to tell if your multicast is getting through is to use the Ehcache remote debugger and watch for the heartbeat packets to arrive.

32.7.3 Multicast Not Propagating Far Enough or Propagating Too FarContents

You can control how far the multicast packets propagate by setting the badly misnamed time to live. Using the multicast IP protocol, the timeToLive value indicates the scope or range in which a packet may be forwarded. By convention:

  0 is restricted to the same host
  1 is restricted to the same subnet
  32 is restricted to the same site
  64 is restricted to the same region
  128 is restricted to the same continent
  255 is unrestricted

The default value in Java is 1, which propagates to the same subnet. Change the timeToLive property to restrict or expand propagation.

--- Distributed Caching using JGroups ---

33 Distributed Caching using JGroupsContents

As of version 1.5, JGroups can be used as the underlying mechanism for the distributed operations in ehcache. JGroups offers a very flexible protocol stack, reliable unicast and multicast message transmission. On the down side JGroups can be complex to configure and some protocol stacks have dependencies on others.

To set up distributed caching using JGroups you need to configure a PeerProviderFactory of type JGroupsCacheManagerPeerProviderFactory which is done globally for a CacheManager For each cache that will operate distributed, you then need to add a cacheEventListenerFactory of type JGroupsCacheReplicatorFactory to propagate messages.

33.1 Suitable Element TypesContents

Only Serializable Elements are suitable for replication.

Some operations, such as remove, work off Element keys rather than the full Element itself. In this case the operation will be replicated provided the key is Serializable, even if the Element is not.

33.2 Peer DiscoveryContents

If you use the UDP multicast stack there is no additional configuration. If you use a TCP stack you will need to specify the initial hosts in the cluster.

33.3 ConfigurationContents

There are two things to configure:

33.4 Example configuration using UDP MulticastContents

Suppose you have two servers in a cluster. You wish to distribute sampleCache11 and sampleCache12 and you wish to use UDP multicast as the underlying mechanism.

The configuration for server1 and server2 are identical and will look like this:

<cacheManagerPeerProviderFactory
     class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"
     properties="connect=UDP(mcast_addr=231.12.21.132;mcast_port=45566;):PING:
     MERGE2:FD_SOCK:VERIFY_SUSPECT:pbcast.NAKACK:UNICAST:pbcast.STABLE:FRAG:pbcast.GMS"
     propertySeparator="::"
     />

33.5 Example configuration using TCP UnicastContents

The TCP protocol requires the IP address of all servers to be known. They are configured through the TCPPING protocol of Jgroups.

Suppose you have 2 servers host1 and host2, then the configuration is:

 <cacheManagerPeerProviderFactory
    class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"
    properties="connect=TCP(start_port=7800):
        TCPPING(initial_hosts=host1[7800],host2[7800];port_range=10;timeout=3000;
        num_initial_members=3;up_thread=true;down_thread=true):
        VERIFY_SUSPECT(timeout=1500;down_thread=false;up_thread=false):
        pbcast.NAKACK(down_thread=true;up_thread=true;gc_lag=100;retransmit_timeout=3000):
        pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;
        print_local_addr=false;down_thread=true;up_thread=true)"
    propertySeparator="::" />

33.6 Protocol considerations.Contents

You should read the JGroups documentation to configure the protocols correctly.

See http://www.jgroups.org/javagroupsnew/docs/manual/html_single/index.html.

If using UDP you should at least configure PING, FD_SOCK (Failure detection), VERIFY_SUSPECT, pbcast.NAKACK (Message reliability), pbcast.STABLE (message garbage collection).

33.7 Configuring CacheReplicatorsContents

Each cache that will be distributed needs to set a cache event listener which then replicates messages to the other CacheManager peers. This is done by adding a cacheEventListenerFactory element to each cache's configuration. The properties are identical to the one used for RMI replication.

The listener factory MUST be of type JGroupsCacheReplicatorFactory.

<!-- Sample cache named sampleCache2. -->
<cache name="sampleCache2"
   maxElementsInMemory="10"
   eternal="false"
   timeToIdleSeconds="100"
   timeToLiveSeconds="100"
   overflowToDisk="false">
   <cacheEventListenerFactory
   class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
   properties="replicateAsynchronously=true, replicatePuts=true,
   replicateUpdates=true, replicateUpdatesViaCopy=false, replicateRemovals=true" />
</cache>

The configuration options are explained below:

class - use net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory

The factory recognises the following properties:

33.8 Complete Sample configurationContents

A typical complete configuration for one replicated cache configured for UDP will look like:

<Ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../main/config/ehcache.xsd">

<diskStore path="java.io.tmpdir/one"/>

<cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.jgroups
    .JGroupsCacheManagerPeerProviderFactory"
     properties="connect=UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_ttl=32;
     mcast_send_buf_size=150000;mcast_recv_buf_size=80000):
     PING(timeout=2000;num_initial_members=6):
     MERGE2(min_interval=5000;max_interval=10000):
     FD_SOCK:VERIFY_SUSPECT(timeout=1500):
     pbcast.NAKACK(gc_lag=10;retransmit_timeout=3000):
     UNICAST(timeout=5000):
     pbcast.STABLE(desired_avg_gossip=20000):
     FRAG:
     pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;
     shun=false;print_local_addr=true)"
 propertySeparator="::"
     />

<cache name="sampleCacheAsync"
   maxElementsInMemory="1000"
   eternal="false"
   timeToIdleSeconds="1000"
   timeToLiveSeconds="1000"
   overflowToDisk="false">
    <cacheEventListenerFactory
    class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
    properties="replicateAsynchronously=true, replicatePuts=true,
replicateUpdates=true, replicateUpdatesViaCopy=false,
replicateRemovals=true" />
</cache>

</ehcache>

33.9 Common ProblemsContents

If replication using JGroups doesnt't work the way you have it configured try this configuration which has been extensively tested:

<cacheManagerPeerProviderFactory
    class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"/>

<cache name="sampleCacheAsync"
   maxElementsInMemory="1000"
   eternal="false"
   timeToIdleSeconds="1000"
   timeToLiveSeconds="1000"
   overflowToDisk="false">
   <cacheEventListenerFactory
    class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
    properties="replicateAsynchronously=true, replicatePuts=true,
    replicateUpdates=true, replicateUpdatesViaCopy=false,
    replicateRemovals=true" />
</cache>

If this fails to replicate, try to get the example programs from JGroups to run:

http://www.jgroups.org/javagroupsnew/docs/manual/html/ch02.html#d0e451

and

http://www.jgroups.org/javagroupsnew/docs/manual/html/ch02.html#ItDoesntWork

Once you have figured out the connection string that works in your network for JGroups, you can directly paste it in the connect property of JGroupsCacheManagerPeerProviderFactory.

--- Distributed Caching using JMS ---

34 Distributed Caching using JMSContents

As of version 1.6, JMS can be used as the underlying mechanism for the distributed operations in Ehcache with the jmsreplication module.

JMS, ("Java Message Service") is an industry standard mechanism for interacting with message queues. Message queues themselves are a very mature piece of infrastructure used in many enterprise software contexts. Because they are a required part of the Java EE specification, the large enterprise vendors all provide their own implementations. There are also several open source choices including Open MQ and Active MQ. Ehcache is integration tested against both of these.

The Ehcache jmsreplication module lets organisations with a message queue investment leverage it for caching.

It provides:

34.1 Ehcache Replication and External PublishersContents

Ehcache replicates using JMS as follows:

34.1.1 ConfigurationContents

34.1.1.1 Message Queue Configuration

Each cluster needs to use a fixed topic name for replication. Set up a topic using the tools in your message queue. Out of the box, both ActiveMQ and Open MQ support auto creation of destinations, so this step may be optional.

34.1.1.2 Ehcache Configuration

Configuration is done in the ehcache.xml.

There are two things to configure:

34.1.1.2.1 Configuring the JMSCacheManagerPeerProviderFactory

Following is the configuration instructions as it appears in the sample ehcache.xml shipped with ehcache:

{Configuring JMS replication}.
===========================

<cacheManagerPeerProviderFactory
        class="net.sf.ehcache.distribution.jms.JMSCacheManagerPeerProviderFactory"
        properties="..."
        propertySeparator=","
        />

The JMS PeerProviderFactory uses JNDI to maintain message queue independence.
Refer to the manual for full configuration examples using ActiveMQ and Open Message Queue.

Valid properties are:
* initialContextFactoryName (mandatory) - the name of the factory used to create the
    message queue initial context.
* providerURL (mandatory) - the JNDI configuration information for the service provider to
use.
* topicConnectionFactoryBindingName (mandatory) - the JNDI binding name for the
    TopicConnectionFactory
* topicBindingName (mandatory) - the JNDI binding name for the topic name
* securityPrincipalName - the JNDI java.naming.security.principal
* securityCredentials - the JNDI java.naming.security.credentials
* urlPkgPrefixes - the JNDI java.naming.factory.url.pkgs
* userName - the user name to use when creating the TopicConnection to the Message Queue
* password - the password to use when creating the TopicConnection to the Message Queue
* acknowledgementMode - the JMS Acknowledgement mode for both publisher and subscriber.
    The available choices are
                        AUTO_ACKNOWLEDGE, DUPS_OK_ACKNOWLEDGE and SESSION_TRANSACTED.
                        The default is AUTO_ACKNOWLEDGE.
* listenToTopic - true or false. If false, this cache will send to the JMS topic but will
    not listen for updates.
* Default is true.
34.1.1.2.2 Example Configurations

Usage is best illustrated with concrete examples for Active MQ and Open MQ.

34.1.1.2.3 Configuring the JMSCacheManagerPeerProviderFactory for Active MQ

This configuration works with Active MQ out of the box.

<cacheManagerPeerProviderFactory
            class="net.sf.ehcache.distribution.jms.JMSCacheManagerPeerProviderFactory"
            properties="initialContextFactoryName=ExampleActiveMQInitialContextFactory,
                providerURL=tcp://localhost:61616,
                topicConnectionFactoryBindingName=topicConnectionFactory,
                topicBindingName=ehcache"
            propertySeparator=","
            />

You need to provide your own ActiveMQInitialContextFactory for the initialContextFactoryName.

An example which should work for most purposes is:

public class ExampleActiveMQInitialContextFactory extends ActiveMQInitialContextFactory {

/**
 * {@inheritDoc}
 */
@Override
@SuppressWarnings("unchecked")
public Context getInitialContext(Hashtable environment) throws NamingException {

    Map<String, Object> data = new ConcurrentHashMap<String, Object>();

    String factoryBindingName = (String)environment.get(JMSCacheManagerPeerProviderFactory
    .TOPIC_CONNECTION_FACTORY_BINDING_NAME);

    try {
        data.put(factoryBindingName, createConnectionFactory(environment));
    } catch (URISyntaxException e) {
        throw new NamingException("Error initialisating ConnectionFactory with message "
        + e.getMessage());
    }

    String topicBindingName = (String)environment.get(JMSCacheManagerPeerProviderFactory
    .TOPIC_BINDING_NAME);

    data.put(topicBindingName, createTopic(topicBindingName));

    return createContext(environment, data);
}
}  
34.1.1.2.4 Configuring the JMSCacheManagerPeerProviderFactory for Open MQ

This configuration works with an out of the box Open MQ.

<cacheManagerPeerProviderFactory
            class="net.sf.ehcache.distribution.jms.JMSCacheManagerPeerProviderFactory"
            properties="initialContextFactoryName=com.sun.jndi.fscontext.RefFSContextFactory,
                providerURL=file:///tmp,
                topicConnectionFactoryBindingName=MyConnectionFactory,
                topicBindingName=ehcache"
            propertySeparator=","
            />

To set up the Open MQ file system initial context to work with this example use the following imqobjmgr commands to create the requires objects in the context.

imqobjmgr add -t tf -l 'MyConnectionFactory' -j java.naming.provider.url \
=file:///tmp -j java.naming.factory.initial=com.sun.jndi.fscontext.RefFSContextFactory -f
imqobjmgr add -t t -l 'ehcache' -o 'imqDestinationName=EhcacheTopicDest'
-j java.naming.provider.url\
=file:///tmp -j java.naming.factory.initial=com.sun.jndi.fscontext.RefFSContextFactory -f
34.1.1.2.5 Configuring the JMSCacheReplicatorFactory

This is the same as configuring any of the cache replicators. The class should be net.sf.ehcache.distribution.jms.JMSCacheReplicatorFactory.

See the following example:

<cache name="sampleCacheAsync"
      maxElementsInMemory="1000"
      eternal="false"
      timeToIdleSeconds="1000"
      timeToLiveSeconds="1000"
      overflowToDisk="false">
   <cacheEventListenerFactory
          class="net.sf.ehcache.distribution.jms.JMSCacheReplicatorFactory"
          properties="replicateAsynchronously=true,
                       replicatePuts=true,
                       replicateUpdates=true,
                       replicateUpdatesViaCopy=true,
                       replicateRemovals=true,
                       asynchronousReplicationIntervalMillis=1000"
           propertySeparator=","/>
</cache>
    

34.1.2 External JMS PublishersContents

Anything that can publish to a message queue can also add cache entries to ehcache. These are called non-cache publishers.

34.1.2.1 Required Message Properties

Publishers need to set up to four String properties on each message: cacheName, action, mimeType and key.

34.1.2.1.1 cacheName Property

A JMS message property which contains the name of the cache to operate on.

If no cacheName is set the message will be ignored. A warning log message will indicate that the message has been ignored.

34.1.2.1.2 action Property

A JMS message property which contains the action to perform on the cache.

Available actions are strings labeled PUT, REMOVE and REMOVE_ALL.

If not set no action is performed. A warning log message will indicate that the message has been ignored.

34.1.2.1.3 mimeType Property

A JMS message property which contains the mimeType of the message. Applies to the PUT action. If not set the message is interpreted as follows:

ObjectMessage - if it is an net.sf.ehcache.Element, then it is treated as such and stored in the cache.

For other objects, a new Element is created using the object in the ObjectMessage as the value and the key property as a key. Because objects are already typed, the mimeType is ignored.

TextMessage - Stored in the cache as value of MimeTypeByteArray. The mimeType should be specified. If not specified it is stored as type text/plain.

BytesMessage - Stored in the cache as value of MimeTypeByteArray. The mimeType should be specified. If not specified it is stored as type application/octet-stream.

Other message types are not supported.

To send XML use a TextMessage or BytesMessage and set the mimeType to application/xml.It will be stored in the cache as a value of MimeTypeByteArray.

The REMOVE and REMOVE_ALL actions do not require a mimeType property.

34.1.2.1.4 key Property

The key in the cache on which to operate on. The key is of type String.

The REMOVE_ALL action does not require a key property.

If an ObjectMessage of type net.sf.ehcache.Element is sent, the key is contained in the element. Any key set as a property is ignored.

If the key is required but not provided, a warning log message will indicate that the message has been ignored.

34.1.2.2 Code Samples

These samples use Open MQ as the message queue and use it with out of the box defaults. They are heavily based on Ehcache's own JMS integration tests. See the test source for more details.

Messages should be sent to the topic that Ehcache is listening on. In these samples it is EhcacheTopicDest.

All samples get a Topic Connection using the following method:

private TopicConnection getMQConnection() throws JMSException {
    com.sun.messaging.ConnectionFactory factory = new com.sun.messaging.ConnectionFactory();
    factory.setProperty(ConnectionConfiguration.imqAddressList, "localhost:7676");
    factory.setProperty(ConnectionConfiguration.imqReconnectEnabled, "true");
    TopicConnection myConnection = factory.createTopicConnection();
    return myConnection;
}

34.1.2.3 PUT a Java Object into an Ehcache JMS Cluster

String payload = "this is an object";
TopicConnection connection = getMQConnection();
connection.start();

TopicSession publisherSession =
    connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);

ObjectMessage message = publisherSession.createObjectMessage(payload);
message.setStringProperty(ACTION_PROPERTY, "PUT");
message.setStringProperty(CACHE_NAME_PROPERTY, "sampleCacheAsync");
//don't set. Should work.
//message.setStringProperty(MIME_TYPE_PROPERTY, null);
//should work. Key should be ignored when sending an element.
message.setStringProperty(KEY_PROPERTY, "1234");


Topic topic = publisherSession.createTopic("EhcacheTopicDest");
TopicPublisher publisher = publisherSession.createPublisher(topic);
publisher.send(message);

connection.stop();

Ehcache will create an Element in cache "sampleCacheAsync" with key "1234" and a Java class String value of "this is an object".

34.1.2.4 PUT XML into an Ehcache JMS Cluster

TopicConnection connection = getMQConnection();
connection.start();

TopicSession publisherSession = connection.createTopicSession(false,
    Session.AUTO_ACKNOWLEDGE);

String value = "<?xml version=\"1.0\"?>\n" +
        "<oldjoke>\n" +
        "<burns>Say <quote>goodnight</quote>,\n" +
        "Gracie.</burns>\n" +
        "<allen><quote>Goodnight, \n" +
        "Gracie.</quote></allen>\n" +
        "<applause/>\n" +
        "</oldjoke>";

TextMessage message = publisherSession.createTextMessage(value);
message.setStringProperty(ACTION_PROPERTY, "PUT");
message.setStringProperty(CACHE_NAME_PROPERTY, "sampleCacheAsync");
message.setStringProperty(MIME_TYPE_PROPERTY, "application/xml");
message.setStringProperty(KEY_PROPERTY, "1234");


Topic topic = publisherSession.createTopic("EhcacheTopicDest");
TopicPublisher publisher = publisherSession.createPublisher(topic);
publisher.send(message);

connection.stop();

Ehcache will create an Element in cache "sampleCacheAsync" with key "1234" and a value of type MimeTypeByteArray.

On a get from the cache the MimeTypeByteArray will be returned. It is an Ehcache value object from which a mimeType and byte[] can be retrieved. The mimeType will be "application/xml". The byte[] will contain the XML String encoded in bytes, using the platform's default charset.

34.1.2.5 PUT arbitrary bytes into an Ehcache JMS Cluster

byte[] bytes = new byte[]{0x34, (byte) 0xe3, (byte) 0x88};
TopicConnection connection = getMQConnection();
connection.start();

TopicSession publisherSession = connection.createTopicSession(false,
    Session.AUTO_ACKNOWLEDGE);

BytesMessage message = publisherSession.createBytesMessage();
message.writeBytes(bytes);
message.setStringProperty(ACTION_PROPERTY, "PUT");
message.setStringProperty(CACHE_NAME_PROPERTY, "sampleCacheAsync");
message.setStringProperty(MIME_TYPE_PROPERTY, "application/octet-stream");
message.setStringProperty(KEY_PROPERTY, "1234");


Topic topic = publisherSession.createTopic("EhcacheTopicDest");
TopicPublisher publisher = publisherSession.createPublisher(topic);
publisher.send(message);

Ehcache will create an Element in cache "sampleCacheAsync" with key "1234" in and a value of type MimeTypeByteArray.

On a get from the cache the MimeTypeByteArray will be returned. It is an Ehcache value object from which a mimeType and byte[] can be retrieved. The mimeType will be "application/octet-stream". The byte[] will contain the original bytes.

34.1.2.6 REMOVE

TopicConnection connection = getMQConnection();
connection.start();

TopicSession publisherSession = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);

ObjectMessage message = publisherSession.createObjectMessage();
message.setStringProperty(ACTION_PROPERTY, "REMOVE");
message.setStringProperty(CACHE_NAME_PROPERTY, "sampleCacheAsync");
message.setStringProperty(KEY_PROPERTY, "1234");


Topic topic = publisherSession.createTopic("EhcacheTopicDest");
TopicPublisher publisher = publisherSession.createPublisher(topic);
publisher.send(message);

Ehcache will remove the Element with key "1234" from cache "sampleCacheAsync" from the cluster.

34.1.2.7 REMOVE_ALL

TopicConnection connection = getMQConnection();
connection.start();

TopicSession publisherSession = connection.createTopicSession(false,
    Session.AUTO_ACKNOWLEDGE);

ObjectMessage message = publisherSession.createObjectMessage();
message.setStringProperty(ACTION_PROPERTY, "REMOVE_ALL");
message.setStringProperty(CACHE_NAME_PROPERTY, "sampleCacheAsync");

Topic topic = publisherSession.createTopic("EhcacheTopicDest");
TopicPublisher publisher = publisherSession.createPublisher(topic);
publisher.send(message);

connection.stop();

Ehcache will remove all Elements from cache "sampleCacheAsync" in the cluster.

34.2 Using the JMSCacheLoaderContents

The JMSCacheLoader is a CacheLoader which loads objects into the cache by sending requests to a JMS Queue.

The loader places an ObjectMessage of type JMSEventMessage on the getQueue with an Action of type GET.

It is configured with the following String properties, loaderArgument.

The defaultLoaderArgument, or the loaderArgument if specified on the load request. To work with the JMSCacheManagerPeerProvider this should be the name of the cache to load from. For custom responders, it can be anything which has meaning to the responder.

A queue responder will respond to the request. You can either create your own or use the one built-into the JMSCacheManagerPeerProviderFactory, which attempts to load the queue from its cache.

The JMSCacheLoader uses JNDI to maintain message queue independence. Refer to the manual for full configuration examples using ActiveMQ and Open Message Queue.

It is configured as per the following example:

<cacheLoaderFactory class="net.sf.ehcache.distribution.jms.JMSCacheLoaderFactory"
   properties="initialContextFactoryName=com.sun.jndi.fscontext.RefFSContextFactory,
providerURL=file:///tmp,
replicationTopicConnectionFactoryBindingName=MyConnectionFactory,
replicationTopicBindingName=ehcache,
getQueueConnectionFactoryBindingName=queueConnectionFactory,
getQueueBindingName=ehcacheGetQueue,
timeoutMillis=20000
defaultLoaderArgument=/>

Valid properties are:

34.2.1 Example Configuration Using Active MQContents

<cache name="sampleCacheNorep"
   maxElementsInMemory="1000"
   eternal="false"
   timeToIdleSeconds="1000"
   timeToLiveSeconds="1000"
   overflowToDisk="false">
   <cacheEventListenerFactory
    class="net.sf.ehcache.distribution.jms.JMSCacheReplicatorFactory"
        properties="replicateAsynchronously=false, replicatePuts=false,
        replicateUpdates=false, replicateUpdatesViaCopy=false,
        replicateRemovals=false, loaderArgument=sampleCacheNorep"
        propertySeparator=","/>
   <cacheLoaderFactory class="net.sf.ehcache.distribution.jms.JMSCacheLoaderFactory"
    properties="initialContextFactoryName=net.sf.ehcache.distribution.jms.
        TestActiveMQInitialContextFactory,
            providerURL=tcp://localhost:61616,
            replicationTopicConnectionFactoryBindingName=topicConnectionFactory,
            getQueueConnectionFactoryBindingName=queueConnectionFactory,
            replicationTopicBindingName=ehcache,
            getQueueBindingName=ehcacheGetQueue,
            timeoutMillis=10000"/>
</cache>

34.2.2 Example Configuration Using Open MQContents

<cache name="sampleCacheNorep"
   maxElementsInMemory="1000"
   eternal="false"
   timeToIdleSeconds="100000"
   timeToLiveSeconds="100000"
   overflowToDisk="false">
   <cacheEventListenerFactory
   class="net.sf.ehcache.distribution.jms.JMSCacheReplicatorFactory"
                           properties="replicateAsynchronously=false, replicatePuts=false,
                             replicateUpdates=false, replicateUpdatesViaCopy=false,
                             replicateRemovals=false"
                           propertySeparator=","/>
   <cacheLoaderFactory class="net.sf.ehcache.distribution.jms.JMSCacheLoaderFactory"
        properties="initialContextFactoryName=com.sun.jndi.fscontext.RefFSContextFactory,
        providerURL=file:///tmp,
        replicationTopicConnectionFactoryBindingName=MyConnectionFactory,
        replicationTopicBindingName=ehcache,
        getQueueConnectionFactoryBindingName=queueConnectionFactory,
        getQueueBindingName=ehcacheGetQueue,
        timeoutMillis=10000,
        userName=test,
        password=test"/>
</cache>

34.3 Configuring Clients for Message Queue ReliabilityContents

Ehcache replication and cache loading is designed to gracefully degrade if the message queue infrastructure stops. Replicates and loads will fail. But when the message queue comes back, these operations will start up again.

For this to work, the ConnectionFactory used with the specific message queue needs to be configured correctly.

For example, with Open MQ, reconnection is configured as follows:

34.4 Tested Message QueuesContents

34.4.1 Sun Open MQContents

This open source message queue is tested in integration tests. It works perfectly.

34.4.2 Active MQContents

This open source message queue is tested in integration tests. It works perfectly other than having a problem with temporary reply queues which prevents the use of JMSCacheLoader. JMSCacheLoader is not used during replication.

34.4.3 Oracle AQContents

Versions up to an including 0.4 do not work, due to Oracle not supporting the unified API (send) for topics.

34.4.4 JBoss QueueContents

Works as reported by a user.

34.5 Known JMS IssuesContents

34.5.1 Active MQ Temporary DestinatonsContents

ActiveMQ seems to have a bug in at least ActiveMQ 5.1 where it does not cleanup temporary queues, even though they have been deleted. That bug appears to be long standing but was though to have been fixed.

See:

34.5.2 WebSphere 5 and 6Contents

Websphere Application Server prevents MessageListeners, which are not MDBs, from being created in the container. While this is a general Java EE limitation, most other app servers either are permissive or can be configured to be permissive. WebSphere 4 worked, but 5 and 6 enforce the restriction.

Accordingly the JMS replicator cannot be used with WebSphere 5 and 6.

--- BlockingCache} and SelfPopulatingCache ---

35 BlockingCache and SelfPopulatingCacheContents

The net.sf.ehcache.constructs package contains some applied caching classes which use the core classes to solve everyday caching problems.

35.1 Blocking CacheContents

Imagine you have a very busy web site with thousands of concurrent users. Rather than being evenly distributed in what they do, they tend to gravitate to popular pages. These pages are not static, they have dynamic data which goes stale in a few minutes. Or imagine you have collections of data which go stale in a few minutes. In each case the data is extremely expensive to calculate.

Let's say each request thread asks for the same thing. That is a lot of work. Now, add a cache. Get each thread to check the cache; if the data is not there, go and get it and put it in the cache. Now, imagine that there are so many users contending for the same data that in the time it takes the first user to request the data and put it in the cache, 10 other users have done the same thing. The upstream system, whether a JSP or velocity page, or interactions with a service layer or database are doing 10 times more work than they need to.

Enter the BlockingCache.

javadoc/net/sf/ehcache/constructs/blocking/BlockingCache

Blocking Cache

It is blocking because all threads requesting the same key wait for the first thread to complete. Once the first thread has completed the other threads simply obtain the cache entry and return.

The BlockingCache can scale up to very busy systems. Each thread can either wait indefinitely, or you can specify a timeout using the timeoutMillis constructor argument.

35.2 SelfPopulatingCacheContents

You want to use the BlockingCache, but the requirement to always release the lock creates gnarly code. You also want to think about what you are doing without thinking about the caching.

Enter the SelfPopulatingCache. The name SelfPopulatingCache is synonymous with Pull-through cache, which is a common caching term. SelfPopulatingCache though always is in addition to a BlockingCache.

SelfPopulatingCache uses a CacheEntryFactory, that given a key, knows how to populate the entry.

Note: JCache inspired getWithLoader and getAllWithLoader directly in Ehcache which work with a CacheLoader may be used as an alternative to SelfPopulatingCache. --- CacheManager Event Listeners ---

36 CacheManager Event ListenersContents

CacheManager event listeners allow implementers to register callback methods that will be executed when a CacheManager event occurs. Cache listeners implement the CacheManagerEventListener interface.

The events include:

Callbacks to these methods are synchronous and unsynchronized. It is the responsibility of the implementer to safely handle the potential performance and thread safety issues depending on what their listener is doing.

36.1 ConfigurationContents

One CacheManagerEventListenerFactory and hence one CacheManagerEventListener can be specified per CacheManager instance.

The factory is configured as below:

<cacheManagerEventListenerFactory class="" properties=""/>

The entry specifies a CacheManagerEventListenerFactory which will be used to create a CacheManagerPeerProvider, which is notified when Caches are added or removed from the CacheManager.

The attributes of CacheManagerEventListenerFactory are:

36.2 Implementing a CacheManagerEventListenerFactory and CacheManagerEventListenerContents

CacheManagerEventListenerFactory is an abstract factory for creating cache manager listeners. Implementers should provide their own concrete factory extending this abstract factory. It can then be configured in ehcache.xml.

The factory class needs to be a concrete subclass of the abstract factory CacheManagerEventListenerFactory, which is reproduced below:

/**
 * An abstract factory for creating {@link CacheManagerEventListener}s. Implementers should
 * provide their own concrete factory extending this factory. It can then be configured in
 * ehcache.xml
 *
 * @author Greg Luck
 * @version $Id: cachemanager_event_listeners.apt 1961 2010-03-02 19:03:27Z gluck $
 * @see "http://ehcache.org/documentation/cachemanager_event_listeners.html"
 */
public abstract class CacheManagerEventListenerFactory {

    /**
     * Create a <code>CacheEventListener</code>
     *
     * @param properties implementation specific properties. These are configured as comma
     *                   separated name value pairs in ehcache.xml. Properties may be null
     * @return a constructed CacheManagerEventListener
     */
    public abstract CacheManagerEventListener
            createCacheManagerEventListener(Properties properties);
}

The factory creates a concrete implementation of CacheManagerEventListener, which is reproduced below:

/**
 * Allows implementers to register callback methods that will be executed when a
 * <code>CacheManager</code> event occurs.
 * The events include:
 * <ol>
 * <li>adding a <code>Cache</code>
 * <li>removing a <code>Cache</code>
 * </ol>
 * <p/>
 * Callbacks to these methods are synchronous and unsynchronized. It is the responsibility of
 * the implementer to safely handle the potential performance and thread safety issues
 * depending on what their listener is doing.
 * @author Greg Luck
 * @version $Id: cachemanager_event_listeners.apt 1961 2010-03-02 19:03:27Z gluck $
 * @since 1.2
 * @see CacheEventListener
 */
public interface CacheManagerEventListener {


/**
 * Called immediately after a cache has been added and activated.
 * <p/>
 * Note that the CacheManager calls this method from a synchronized method. Any attempt to
 * call a synchronized method on CacheManager from this method will cause a deadlock.
 * <p/>
 * Note that activation will also cause a CacheEventListener status change notification
 * from {@link net.sf.ehcache.Status#STATUS_UNINITIALISED} to
 * {@link net.sf.ehcache.Status#STATUS_ALIVE}. Care should be taken on processing that
 * notification because:
 * <ul>
 * <li>the cache will not yet be accessible from the CacheManager.
 * <li>the addCaches methods whih cause this notification are synchronized on the
 * CacheManager. An attempt to call {@link net.sf.ehcache.CacheManager#getCache(String)}
 * will cause a deadlock.
 * </ul>
 * The calling method will block until this method returns.
 * <p/>
 * @param cacheName the name of the <code>Cache</code> the operation relates to
 * @see CacheEventListener
 */
void notifyCacheAdded(String cacheName);

/**
 * Called immediately after a cache has been disposed and removed. The calling method will
 * block until this method returns.
 * <p/>
 * Note that the CacheManager calls this method from a synchronized method. Any attempt to
 * call a synchronized method on CacheManager from this method will cause a deadlock.
 * <p/>
 * Note that a {@link CacheEventListener} status changed will also be triggered. Any
 * attempt from that notification to access CacheManager will also result in a deadlock.
 * @param cacheName the name of the <code>Cache</code> the operation relates to
 */
void notifyCacheRemoved(String cacheName);

}

The implementations need to be placed in the classpath accessible to ehcache. Ehcache uses the ClassLoader returned by Thread.currentThread().getContextClassLoader() to load classes.

--- Cache Loaders ---

37 Cache LoadersContents

A CacheLoader is an interface which specifies load and loadAll methods with a variety of parameters.

CacheLoaders come from JCache, but are a frequently requested feature, so they have been incorporated into the core Ehcache classes and can be configured in ehcache.xml.

CacheLoaders are invoked in the following Cache methods:

They are also invoked in similar (though slightly differently named) JCache methods.

The methods will invoke a CacheLoader if there is no entry for the key or keys requested. By implementing CacheLoader, an application form of loading can take place. The get... methods follow the pull-through cache pattern. The load... methods are useful as cache warmers.

CacheLoaders are similar to the CacheEntryFactory used in SelfPopulatingCache. However SelfPopulatingCache is a decorator to ehcache. The CacheLoader functionality is available right in a Cache, Ehcache or JCache and follows a more industry standard convention.

CacheLoaders may be set either declaratively in the ehcache.xml configuration file or programmatically. This becomes the default CacheLoader. Some of the methods invoking loaders enable an override CacheLoader to be passed in as a parameter.

More than one cacheLoader can be registered, in which case the loaders form a chain which are executed in order. If a loader returns null, the next in chain is called.

37.1 Declarative ConfigurationContents

cacheLoaderFactory - Specifies a CacheLoader, which can be used both asynchronously and synchronously to load objects into a cache. More than one cacheLoaderFactory element can be added, in which case the loaders form a chain which are executed in order. If a loader returns null, the next in chain is called.

<cache ...>
      <cacheLoaderFactory class="com.example.ExampleCacheLoaderFactory"
                                      properties="type=int,startCounter=10"/>
</cache>

37.2 Implementing a CacheLoaderFactory and CacheLoaderContents

CacheLoaderFactory is an abstract factory for creating CacheLoaders. Implementers should provide their own concrete factory, extending this abstract factory. It can then be configured in ehcache.xml

The factory class needs to be a concrete subclass of the abstract factory class CacheLoaderFactory, which is reproduced below:

/**
 * An abstract factory for creating cache loaders. Implementers should provide their own
 * concrete factory extending this factory.
 * <p/>
 * There is one factory method for JSR107 Cache Loaders and one for Ehcache ones. The Ehcache
 * loader is a sub interface of the JSR107 Cache Loader.
 * <p/>
 * Note that both the JCache and Ehcache APIs also allow the CacheLoader to be set
 * programmatically.
 * @author Greg Luck
 * @version $Id: cache_loaders.apt 1512 2009-12-11 02:15:16Z gluck $
 */
public abstract class CacheLoaderFactory {

/**
 * Creates a CacheLoader using the JSR107 creational mechanism.
 * This method is called from {@link net.sf.ehcache.jcache.JCacheFactory}
 *
 * @param environment the same environment passed into
 * {@link net.sf.ehcache.jcache.JCacheFactory}.
 * This factory can extract any properties it needs from the environment.
 * @return a constructed CacheLoader
 */
public abstract net.sf.jsr107cache.CacheLoader createCacheLoader(Map environment);


/**
 * Creates a CacheLoader using the Ehcache configuration mechanism at the time
 * the associated cache is created.
 *
 * @param properties implementation specific properties. These are configured as comma
 *                   separated name value pairs in ehcache.xml
 * @return a constructed CacheLoader
 */
public abstract net.sf.ehcache.loader.CacheLoader createCacheLoader(Properties properties);

/**
 * @param cache the cache this extension should hold a reference to,
 * and to whose lifecycle it should be bound.
 * @param properties implementation specific properties configured as delimiter
 *  separated name value pairs in ehcache.xml
 * @return a constructed CacheLoader
 */
public abstract CacheLoader createCacheLoader(Ehcache cache, Properties properties);

}

The factory creates a concrete implementation of the CacheLoader interface, which is reproduced below.

A CacheLoader is bound to the lifecycle of a cache, so that init() is called during cache initialization, and dispose() is called on disposal of a cache.

/**
 * Extends JCache CacheLoader with load methods that take an argument in addition to a key
 * @author Greg Luck
 * @version $Id: cache_loaders.apt 1512 2009-12-11 02:15:16Z gluck $
 */
public interface CacheLoader extends net.sf.jsr107cache.CacheLoader {

/**
 * Load using both a key and an argument.
 * <p/>
 * JCache will call through to the load(key) method, rather than this method,
 * where the argument is null.
 *
 * @param key      the key to load the object for
 * @param argument can be anything that makes sense to the loader
 * @return the Object loaded
 * @throws CacheException
 */
Object load(Object key, Object argument) throws CacheException;

/**
 * Load using both a key and an argument.
 * <p/>
 * JCache will use the loadAll(key) method where the argument is null.
 *
 * @param keys     the keys to load objects for
 * @param argument can be anything that makes sense to the loader
 * @return a map of Objects keyed by the collection of keys passed in.
 * @throws CacheException
 */
Map loadAll(Collection keys, Object argument) throws CacheException;

/**
 * Gets the name of a CacheLoader
 *
 * @return the name of this CacheLoader
 */
String getName();

/**
 * Creates a clone of this extension. This method will only be called by Ehcache before a
 * cache is initialized.
 * <p/>
 * Implementations should throw CloneNotSupportedException if they do not support clone
 * but that will stop them from being used with defaultCache.
 *
 * @return a clone
 * @throws CloneNotSupportedException if the extension could not be cloned.
 */
public CacheLoader clone(Ehcache cache) throws CloneNotSupportedException;


/**
 * Notifies providers to initialise themselves.
 * <p/>
 * This method is called during the Cache's initialise method after it has changed it's
 * status to alive. Cache operations are legal in this method.
 *
 * @throws net.sf.ehcache.CacheException
 */
void init();

/**
 * Providers may be doing all sorts of exotic things and need to be able to clean up on
 * dispose.
 * <p/>
 * Cache operations are illegal when this method is called. The cache itself is partly
 * disposed when this method is called.
 *
 * @throws net.sf.ehcache.CacheException
 */
void dispose() throws net.sf.ehcache.CacheException;


/**
 * @return the status of the extension
 */
public Status getStatus();
}

The implementations need to be placed in the classpath accessible to ehcache.

See the chapter on Classloading for details on how classloading of these classes will be done.

37.3 Programmatic ConfigurationContents

The following methods on Cache allow runtime interrogation, registration and unregistration of loaders:

/**
 * Register a {@link CacheLoader} with the cache. It will then be tied into the cache
 *   lifecycle.
 * <p/>
 * If the CacheLoader is not initialised, initialise it.
 *
 * @param cacheLoader A Cache Loader to register
 */
public void registerCacheLoader(CacheLoader cacheLoader) {
    registeredCacheLoaders.add(cacheLoader);
}

/**
 * Unregister a {@link CacheLoader} with the cache. It will then be detached from the cache
 * lifecycle.
 *
 * @param cacheLoader A Cache Loader to unregister
 */
public void unregisterCacheLoader(CacheLoader cacheLoader) {
    registeredCacheLoaders.remove(cacheLoader);
}


/**
 * @return the cache loaders as a live list
 */
public List<CacheLoader> getRegisteredCacheLoaders() {
    return registeredCacheLoaders;
}

--- Cache Event Listeners ---

38 Cache Event ListenersContents

Cache listeners allow implementers to register callback methods that will be executed when a cache event occurs. Cache listeners implement the CacheEventListener interface.

The events include:

Callbacks to these methods are synchronous and unsynchronized. It is the responsibility of the implementer to safely handle the potential performance and thread safety issues depending on what their listener is doing.

Listeners are guaranteed to be notified of events in the order in which they occurred.

Elements can be put or removed from a Cache without notifying listeners by using the putQuiet and removeQuiet methods.

New feature in Ehcache 2.0 In clustered environments event propagation can be configured to be propagated only locally, only remotely, or both. The default is both, to be backwardly compatible.

38.1 ConfigurationContents

Cache event listeners are configured per cache. Each cache can have multiple listeners.

Each listener is configured by adding a cacheManagerEventListenerFactory element as follows:

<cache ...>
<cacheEventListenerFactory class="" properties="" listenFor=""/>
...
</cache>

The entry specifies a CacheManagerEventListenerFactory which is used to create a CachePeerProvider, which then receives notifications.

The attributes of CacheManagerEventListenerFactory are:

38.2 Implementing a CacheEventListenerFactory and CacheEventListenerContents

CacheEventListenerFactory is an abstract factory for creating cache event listeners. Implementers should provide their own concrete factory, extending this abstract factory. It can then be configured in ehcache.xml

The factory class needs to be a concrete subclass of the abstract factory class CacheEventListenerFactory, which is reproduced below:

/**
 * An abstract factory for creating listeners. Implementers should provide their own
 * concrete factory extending this factory. It can then be configured in ehcache.xml
 *
 * @author Greg Luck
 * @version $Id: cache_event_listeners.apt 1961 2010-03-02 19:03:27Z gluck $
 */
public abstract class CacheEventListenerFactory {

/**
 * Create a <code>CacheEventListener</code>
 *
 * @param properties implementation specific properties. These are configured as comma
 *                   separated name value pairs in ehcache.xml
 * @return a constructed CacheEventListener
 */
public abstract CacheEventListener createCacheEventListener(Properties properties);

}

The factory creates a concrete implementation of the CacheEventListener interface, which is reproduced below:

/**
 * Allows implementers to register callback methods that will be executed when a cache event
 *  occurs.
 * The events include:
 * <ol>
 * <li>put Element
 * <li>update Element
 * <li>remove Element
 * <li>an Element expires, either because timeToLive or timeToIdle has been reached.
 * </ol>
 * <p/>
 * Callbacks to these methods are synchronous and unsynchronized. It is the responsibility of
 * the implementer to safely handle the potential performance and thread safety issues
 * depending on what their listener is doing.
 * <p/>
 * Events are guaranteed to be notified in the order in which they occurred.
 * <p/>
 * Cache also has putQuiet and removeQuiet methods which do not notify listeners.
 *
 * @author Greg Luck
 * @version $Id: cache_event_listeners.apt 1961 2010-03-02 19:03:27Z gluck $
 * @see CacheManagerEventListener
 * @since 1.2
 */
public interface CacheEventListener extends Cloneable {

/**
 * Called immediately after an element has been removed. The remove method will block until
 * this method returns.
 * <p/>
 * Ehcache does not chech for
 * <p/>
 * As the {@link net.sf.ehcache.Element} has been removed, only what was the key of the
 * element is known.
 * <p/>
 *
 * @param cache   the cache emitting the notification
 * @param element just deleted
 */
void notifyElementRemoved(final Ehcache cache, final Element element) throws CacheException;

/**
 * Called immediately after an element has been put into the cache. The
 * {@link net.sf.ehcache.Cache#put(net.sf.ehcache.Element)} method
 * will block until this method returns.
 * <p/>
 * Implementers may wish to have access to the Element's fields, including value, so the
 * element is provided. Implementers should be careful not to modify the element. The
 * effect of any modifications is undefined.
 *
 * @param cache   the cache emitting the notification
 * @param element the element which was just put into the cache.
 */
void notifyElementPut(final Ehcache cache, final Element element) throws CacheException;

/**
 * Called immediately after an element has been put into the cache and the element already
 * existed in the cache. This is thus an update.
 * <p/>
 * The {@link net.sf.ehcache.Cache#put(net.sf.ehcache.Element)} method
 * will block until this method returns.
 * <p/>
 * Implementers may wish to have access to the Element's fields, including value, so the
 * element is provided. Implementers should be careful not to modify the element. The
 * effect of any modifications is undefined.
 *
 * @param cache   the cache emitting the notification
 * @param element the element which was just put into the cache.
 */
void notifyElementUpdated(final Ehcache cache, final Element element) throws CacheException;


/**
 * Called immediately after an element is <i>found</i> to be expired. The
 * {@link net.sf.ehcache.Cache#remove(Object)} method will block until this method returns.
 * <p/>
 * As the {@link Element} has been expired, only what was the key of the element is known.
 * <p/>
 * Elements are checked for expiry in Ehcache at the following times:
 * <ul>
 * <li>When a get request is made
 * <li>When an element is spooled to the diskStore in accordance with a MemoryStore
 * eviction policy
 * <li>In the DiskStore when the expiry thread runs, which by default is
 * {@link net.sf.ehcache.Cache#DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS}
 * </ul>
 * If an element is found to be expired, it is deleted and this method is notified.
 *
 * @param cache   the cache emitting the notification
 * @param element the element that has just expired
 *    <p/>
 *    Deadlock Warning: expiry will often come from the <code>DiskStore</code>
 *    expiry thread. It holds a lock to the DiskStorea the time the
 *    notification is sent. If the implementation of this method calls into a
 *    synchronized <code>Cache</code> method and that subsequently calls into
 *    DiskStore a deadlock will result. Accordingly implementers of this method
 *    should not call back into Cache.
 */
void notifyElementExpired(final Ehcache cache, final Element element);


/**
 * Give the replicator a chance to cleanup and free resources when no longer needed
 */
void dispose();


/**
 * Creates a clone of this listener. This method will only be called by Ehcache before a
 * cache is initialized.
 * <p/>
 * This may not be possible for listeners after they have been initialized. Implementations
 * should throw CloneNotSupportedException if they do not support clone.
 * @return a clone
 * @throws CloneNotSupportedException if the listener could not be cloned.
 */
public Object clone() throws CloneNotSupportedException;

}

The implementations need to be placed in the classpath accessible to Ehcache.

See the chapter on Classloading for details on how classloading of these classes will be done.

--- Cache Exception Handlers ---

39 Cache Exception HandlersContents

By default, most cache operations will propagate a runtime CacheException on failure. An interceptor, using a dynamic proxy, may be configured so that a CacheExceptionHandler can be configured to intercept Exceptions. Errors are not intercepted.

Caches with ExceptionHandling configured are of type Ehcache. To get the exception handling behaviour they must be referenced using CacheManager.getEhcache(), not CacheManager.getCache(), which returns the underlying undecorated cache.

CacheExceptionHandlers may be set either declaratively in the ehcache.xml configuration file or programmatically.

39.1 Declarative ConfigurationContents

Cache event listeners are configured per cache. Each cache can have at most one exception handler.

An exception handler is configured by adding a cacheExceptionHandlerFactory element as shown in the following example:

<cache ...>
      <cacheExceptionHandlerFactory
        class="net.sf.ehcache.exceptionhandler.CountingExceptionHandlerFactory"
        properties="logLevel=FINE"/>
</cache>

39.2 Implementing a CacheExceptionHandlerFactory and CacheExceptionHandlerContents

CacheExceptionHandlerFactory is an abstract factory for creating cache exception handlers. Implementers should provide their own concrete factory, extending this abstract factory. It can then be configured in ehcache.xml

The factory class needs to be a concrete subclass of the abstract factory class CacheExceptionHandlerFactory, which is reproduced below:

/**
 * An abstract factory for creating <code>CacheExceptionHandler</code>s at configuration
 * time, in ehcache.xml.
 * <p/>
 * Extend to create a concrete factory
 *
 * @author <a href="mailto:gluck@gregluck.com">Greg Luck</a>
 * @version $Id: cache_exception_handlers.apt 1512 2009-12-11 02:15:16Z gluck $
 */
public abstract class CacheExceptionHandlerFactory {

/**
 * Create an <code>CacheExceptionHandler</code>
 *
 * @param properties implementation specific properties. These are configured as comma
 *                   separated name value pairs in ehcache.xml
 * @return a constructed CacheExceptionHandler
 */
public abstract CacheExceptionHandler createExceptionHandler(Properties properties);


}

The factory creates a concrete implementation of the CacheExceptionHandler interface, which is reproduced below:

/**
 * A handler which may be registered with an Ehcache, to handle exception on Cache operations.
 * <p/>
 * Handlers may be registered at configuration time in ehcache.xml, using a
 * CacheExceptionHandlerFactory, or *  set at runtime (a strategy).
 * <p/>
 * If an exception handler is registered, the default behaviour of throwing the exception
 * will not occur. The handler * method <code>onException</code> will be called. Of course, if
 * the handler decides to throw the exception, it will * propagate up through the call stack.
 * If the handler does not, it won't.
 * <p/>
 * Some common Exceptions thrown, and which therefore should be considered when implementing
 * this class are listed below:
 * <ul>
 * <li>{@link IllegalStateException} if the cache is not
 * {@link net.sf.ehcache.Status#STATUS_ALIVE}
 * <li>{@link IllegalArgumentException} if an attempt is made to put a null
 * element into a cache
 * <li>{@link net.sf.ehcache.distribution.RemoteCacheException} if an issue occurs
 *  in remote synchronous replication
 * <li>
 * <li>
 * </ul>
 *
 * @author <a href="mailto:gluck@gregluck.com">Greg Luck</a>
 * @version $Id: cache_exception_handlers.apt 1512 2009-12-11 02:15:16Z gluck $
 */
public interface CacheExceptionHandler {

/**
 * Called if an Exception occurs in a Cache method. This method is not called
 * if an <code>Error</code> occurs.
 *
 * @param Ehcache   the cache in which the Exception occurred
 * @param key       the key used in the operation, or null if the operation does not use a
 * key or the key was null
 * @param exception the exception caught
 */
void onException(Ehcache ehcache, Object key, Exception exception);
}

The implementations need to be placed in the classpath accessible to Ehcache.

See the chapter on Classloading for details on how classloading of these classes will be done.

39.3 Programmatic ConfigurationContents

The following example shows how to add exception handling to a cache then adding the cache back into cache manager so that all clients obtain the cache handling decoration.

    CacheManager cacheManager = ...
    Ehcache cache = cacheManger.getCache("exampleCache");
    ExceptionHandler handler = new ExampleExceptionHandler(...);
    cache.setCacheLoader(handler);
    Ehcache proxiedCache = ExceptionHandlingDynamicCacheProxy.createProxy(cache);
    cacheManager.replaceCacheWithDecoratedCache(cache, proxiedCache);

--- Cache Extensions ---

40 Cache ExtensionsContents

CacheExtensions are a general purpose mechanism to allow generic extensions to a Cache.

CacheExtensions are tied into the Cache lifecycle. For that reason this interface has the lifecycle methods.

CacheExtensions are created using the CacheExtensionFactory which has a codecreateCacheCacheExtension()/code method which takes as a parameter a Cache and properties. It can thus call back into any public method on Cache, including, of course, the load methods.

CacheExtensions are suitable for timing services, where you want to create a timer to perform cache operations. The other way of adding Cache behaviour is to decorate a cache.

See @link net.sf.ehcache.constructs.blocking.BlockingCache for an example of how to do this.

Because a CacheExtension holds a reference to a Cache, the CacheExtension can do things such as registering a CacheEventListener or even a CacheManagerEventListener, all from within a CacheExtension, creating more opportunities for customisation.

40.1 Declarative ConfigurationContents

Cache extension are configured per cache. Each cache can have zero or more.

A CacheExtension is configured by adding a cacheExceptionHandlerFactory element as shown in the following example:

<cache ...>
 <cacheExtensionFactory class="com.example.FileWatchingCacheRefresherExtensionFactory"
     properties="refreshIntervalMillis=18000, loaderTimeout=3000,
                 flushPeriod=whatever, someOtherProperty=someValue ..."/>

</cache>

40.2 Implementing a CacheExtensionFactory and CacheExtensionContents

CacheExtensionFactory is an abstract factory for creating cache extension. Implementers should provide their own concrete factory, extending this abstract factory. It can then be configured in ehcache.xml

The factory class needs to be a concrete subclass of the abstract factory class CacheExtensionFactory, which is reproduced below:

/**
 * An abstract factory for creating <code>CacheExtension</code>s. Implementers should
 * provide their own * concrete factory extending this factory. It can then be configured
 * in ehcache.xml.
 *
 * @author <a href="mailto:gluck@gregluck.com">Greg Luck</a>
 * @version $Id: cache_extensions.apt 1512 2009-12-11 02:15:16Z gluck $
 */
public abstract class CacheExtensionFactory {

/**
 * @param cache the cache this extension should hold a reference to, and to whose
 * lifecycle it should be bound.
 * @param properties implementation specific properties configured as delimiter separated
 * name value pairs in ehcache.xml
 */
public abstract CacheExtension createCacheExtension(Ehcache cache, Properties properties);

}

The factory creates a concrete implementation of the CacheExtension interface, which is reproduced below:

/**
 * This is a general purpose mechanism to allow generic extensions to a Cache.
 * <p/>
 * CacheExtensions are tied into the Cache lifecycle. For that reason this interface has the
 *  lifecycle methods.
 * <p/>
 * CacheExtensions are created using the CacheExtensionFactory which has a
 * <code>createCacheCacheExtension()</code> method which takes as a parameter a Cache and
 * properties. It can thus call back into any public method on Cache, including, of course,
 *  the load methods.
 * <p/>
 * CacheExtensions are suitable for timing services, where you want to create a timer to
 * perform cache operations. The other way of adding Cache behaviour is to decorate a cache.
 * See {@link net.sf.ehcache.constructs.blocking.BlockingCache} for an example of how to do
 * this.
 * <p/>
 * Because a CacheExtension holds a reference to a Cache, the CacheExtension can do things
 * such as registering a CacheEventListener or even a CacheManagerEventListener, all from
 * within a CacheExtension, creating more opportunities for customisation.
 *
 * @author <a href="mailto:gluck@gregluck.com">Greg Luck</a>
 * @version $Id: cache_extensions.apt 1512 2009-12-11 02:15:16Z gluck $
 */
public interface CacheExtension {

/**
 * Notifies providers to initialise themselves.
 * <p/>
 * This method is called during the Cache's initialise method after it has changed it's
 * status to alive. Cache operations are legal in this method.
 *
 * @throws CacheException
 */
void init();

/**
 * Providers may be doing all sorts of exotic things and need to be able to clean up on
 * dispose.
 * <p/>
 * Cache operations are illegal when this method is called. The cache itself is partly
 * disposed when this method is called.
 *
 * @throws CacheException
 */
void dispose() throws CacheException;

/**
 * Creates a clone of this extension. This method will only be called by Ehcache before a
 * cache is initialized.
 * <p/>
 * Implementations should throw CloneNotSupportedException if they do not support clone
 * but that will stop them from being used with defaultCache.
 *
 * @return a clone
 * @throws CloneNotSupportedException if the extension could not be cloned.
 */
public CacheExtension clone(Ehcache cache) throws CloneNotSupportedException;


/**
 * @return the status of the extension
 */
public Status getStatus();
}

The implementations need to be placed in the classpath accessible to ehcache.

See the chapter on Classloading for details on how class loading of these classes will be done.

40.3 Programmatic ConfigurationContents

Cache Extensions may also be programmatically added to a Cache as shown.

    TestCacheExtension testCacheExtension = new TestCacheExtension(cache, ...);
    testCacheExtension.init();
    cache.registerCacheExtension(testCacheExtension);

--- Cache Server ---

41 Cache ServerContents

41.1 IntroductionContents

Ehcache now comes with a Cache Server, available as a WAR for most web containers, or as a standalone server. The Cache Server has two APIs: RESTful resource oriented, and SOAP. Both support clients in any programming language.

(A Note on terminology: Leonard Richardson and Sam Ruby have done a great job of clarifying the different Web Services architectures and distinguishing them from each other. We use their taxonomy in describing web services. See http://www.oreilly.com/catalog/9780596529260/.)

41.2 RESTful Web ServicesContents

Roy Fielding coined the acronym REST, denoting Representational State Transfer, in his PhD thesis.

The Ehcache implementation strictly follows the RESTful resource-oriented architecture style.

Specifically:

41.2.1 RESTFul Web Services APIContents

The Ehcache RESTFul Web Services API exposes the singleton CacheManager, which typically has been configured in ehcache.xml or an IoC container. Multiple CacheManagers are not supported.

Resources are identified using a URI template. The value in parentheses should be substituted with a literal to specify a resource.

Response codes and response headers strictly follow HTTP conventions.

41.2.2 CacheManager Resource OperationsContents

41.2.2.1 OPTIONS /{cache}}

Retrieves the WADL for describing the available CacheManager operations.

41.2.2.2 GET /

Lists the Caches in the CacheManager.

41.2.3 Cache Resource OperationsContents

41.2.3.1 OPTIONS /{cache}}

Retrieves the WADL describing the available Cache operations.

41.2.3.2 HEAD /{cache}}

Retrieves the same metadata a GET would receive returned as HTTP headers. There is no body returned.

41.2.3.3 GET /{cache}

Gets a cache representation. This includes useful metadata such as the configuration and cache statistics.

41.2.3.4 PUT /{cache}

Creates a Cache using the defaultCache configuration.

41.2.3.5 DELETE / {cache}

Deletes the Cache.

41.2.4 Element Resource OperationsContents

41.2.4.1 OPTIONS /{cache}}

Retrieves the WADL describing the available Element operations.

41.2.4.2 HEAD /{cache}/{element}

Retrieves the same metadata a GET would receive returned as HTTP headers. There is no body returned.

41.2.4.3 GET /{cache}/{element}

Gets the element value.

41.2.4.4 HEAD /{cache}/{element}

Gets the element's metadata.

41.2.4.5 PUT /{cache}/{element}

Puts an element into the Cache.

The time to live of new Elements defaults to that for the cache. This may be overridden by setting the HTTP request header ehcacheTimeToLiveSeconds. Values of 0 to 2147483647 are accepted. A value of 0 means eternal.

41.2.4.6 DELETE / {cache}/{element}

Deletes the element from the cache.

The resource representation for all elements is *. DELETE/{cache}/* will call <<<cache.removeAll().

41.2.5 Resource RepresentationsContents

We deal with resource representations rather than resources themselves.

41.2.5.1 Element Resource Representations

When Elements are PUT into the cache, a MIME Type should be set in the request header. The MIME Type is preserved for later use.

The new MimeTypeByteArray is used to store the byte[] and the MimeType in the value field of Element.

Some common MIME Types which are expected to be used by clients are:

text/plain Plain text
text/xml Extensible Markup Language. Defined in RFC 3023
application/json JavaScript Object Notation JSON. Defined in RFC 4627
application/x-java-serialized-object A serialized Java object

Because Ehcache is a distributed Java cache, in some configurations the Cache server may contain Java objects that arrived at the Cache server via distributed replication. In this case no MIME Type will be set and the Element will be examined to determine its MIME Type.

Because anything that can be PUT into the cache server must be Serializable, it can also be distributed in a cache cluster i.e. it will be Serializable.

41.2.6 RESTful Code SamplesContents

These are RESTful code samples in multiple languages.

41.2.6.1 Curl Code Samples

These samples use the popular curl command line utility.

41.2.6.1.1 OPTIONS

This example shows how calling OPTIONS causes Ehcache server to respond with the WADL for that resource

curl --request OPTIONS http://localhost:8080/ehcache/rest/sampleCache2/2

The server responds with:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<application xmlns="http://research.sun.com/wadl/2006/10">
<resources base="http://localhost:8080/ehcache/rest/">
<resource path="sampleCache2/2">
<method name="HEAD"><response><representation mediaType="
    ...
</resource>
</resources>
</application>
41.2.6.1.2 HEAD
curl --head  http://localhost:8080/ehcache/rest/sampleCache2/2

The server responds with:

HTTP/1.1 200 OK
X-Powered-By: Servlet/2.5
Server: GlassFish/v3
Last-Modified: Sun, 27 Jul 2008 08:08:49 GMT
ETag: "1217146129490"
Content-Type: text/plain; charset=iso-8859-1
Content-Length: 157
Date: Sun, 27 Jul 2008 08:17:09 GMT
41.2.6.1.3 PUT
echo "Hello World" |  curl -S -T -  http://localhost:8080/ehcache/rest/sampleCache2/3

The server will put Hello World into sampleCache2 using key 3.

41.2.6.1.4 GET
curl http://localhost:8080/ehcache/rest/sampleCache2/2

The server responds with:

<?xml version="1.0"?>
<oldjoke>
<burns>Say <quote>goodnight</quote>,
Gracie.</burns>
<allen><quote>Goodnight,
Gracie.</quote></allen>
<applause/>

41.2.6.2 Ruby Code Samples

41.2.6.2.1 GET
require 'rubygems'
require 'open-uri'
require 'rexml/document'


response = open('http://localhost:8080/ehcache/rest/sampleCache2/2')
xml = response.read
puts xml

The server responds with:

<?xml version="1.0"?>
<oldjoke>
<burns>Say <quote>goodnight</quote>,
Gracie.</burns>
<allen><quote>Goodnight,
Gracie.</quote></allen>
<applause/>
</oldjoke>

41.2.6.3 Python Code Samples

41.2.6.3.1 GET
import urllib2

f = urllib2.urlopen('http://localhost:8080/ehcache/rest/sampleCache2/2')
print f.read()

The server responds with:

<?xml version="1.0"?>
<oldjoke>
<burns>Say <quote>goodnight</quote>,
Gracie.</burns>
<allen><quote>Goodnight,
Gracie.</quote></allen>
<applause/>
</oldjoke>

41.2.6.4 Java Code Samples

41.2.6.4.1 Create and Get a Cache and Entry
package samples;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * A simple example Java client which uses the built-in java.net.URLConnection.
 *
 * @author BryantR
 * @author Greg Luck
 */
public class ExampleJavaClient {

    private static String TABLE_COLUMN_BASE =
            "http://localhost:8080/ehcache/rest/tableColumn";
    private static String TABLE_COLUMN_ELEMENT =
            "http://localhost:8080/ehcache/rest/tableColumn/1";

    /**
     * Creates a new instance of EHCacheREST
     */
    public ExampleJavaClient() {
    }

    public static void main(String[] args) {
        URL url;
        HttpURLConnection connection = null;
        InputStream is = null;
        OutputStream os = null;
        int result = 0;
        try {
            //create cache
            URL u = new URL(TABLE_COLUMN_BASE);
            HttpURLConnection urlConnection = (HttpURLConnection) u.openConnection();
            urlConnection.setRequestMethod("PUT");

            int status = urlConnection.getResponseCode();
            System.out.println("Status: " + status);
            urlConnection.disconnect();

            //get cache
            url = new URL(TABLE_COLUMN_BASE);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            is = connection.getInputStream();
            byte[] response1 = new byte[4096];
            result = is.read(response1);
            while (result != -1) {
                System.out.write(response1, 0, result);
                result = is.read(response1);
            }
            if (is != null) try {
                is.close();
            } catch (Exception ignore) {
            }
            System.out.println("reading cache: " + connection.getResponseCode()
                    + " " + connection.getResponseMessage());
            if (connection != null) connection.disconnect();

            //create entry
            url = new URL(TABLE_COLUMN_ELEMENT);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestProperty("Content-Type", "text/plain");
            connection.setDoOutput(true);
            connection.setRequestMethod("PUT");
            connection.connect();
            String sampleData = "Ehcache is way cool!!!";
            byte[] sampleBytes = sampleData.getBytes();
            os = connection.getOutputStream();
            os.write(sampleBytes, 0, sampleBytes.length);
            os.flush();
            System.out.println("result=" + result);
            System.out.println("creating entry: " + connection.getResponseCode()
                    + " " + connection.getResponseMessage());
            if (connection != null) connection.disconnect();

            //get entry
            url = new URL(TABLE_COLUMN_ELEMENT);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            is = connection.getInputStream();
            byte[] response2 = new byte[4096];
            result = is.read(response2);
            while (result != -1) {
                System.out.write(response2, 0, result);
                result = is.read(response2);
            }
            if (is != null) try {
                is.close();
            } catch (Exception ignore) {
            }
            System.out.println("reading entry: " + connection.getResponseCode()
                    + " " + connection.getResponseMessage());
            if (connection != null) connection.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (os != null) try {
                os.close();
            } catch (Exception ignore) {
            }
            if (is != null) try {
                is.close();
            } catch (Exception ignore) {
            }
            if (connection != null) connection.disconnect();
        }
    }
}

41.2.6.5 Scala Code Samples

41.2.6.5.1 GET
   import java.net.URL
   import scala.io.Source.fromInputStream

   object ExampleScalaGet extends Application {
     val url = new URL("http://localhost:8080/ehcache/rest/sampleCache2/2")
     fromInputStream(url.openStream).getLines.foreach(print)
   }

Run it with:

    scala -e ExampleScalaGet

The program outputs:

     <?xml version="1.0"?>
     <oldjoke>
     <burns>Say <quote>goodnight</quote>,
     Gracie.</burns>
     <allen><quote>Goodnight,
     Gracie.</quote></allen>
     <applause/>

41.2.6.6 PHP Code Samples

41.2.6.6.1 GET
   <?php

   $ch = curl_init();

   curl_setopt ($ch, CURLOPT_URL, "http://localhost:8080/ehcache/rest/sampleCache2/3");
   curl_setopt ($ch, CURLOPT_HEADER, 0);

   curl_exec ($ch);

   curl_close ($ch);
   ?>

The server responds with:

Hello Ingo
41.2.6.6.2 PUT
   <?php
$url = "http://localhost:8080/ehcache/rest/sampleCache2/3";
$localfile = "localfile.txt";

$fp = fopen ($localfile, "r");
$ch = curl_init();
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_PUT, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($localfile));

$http_result = curl_exec($ch);
$error = curl_error($ch);
$http_code = curl_getinfo($ch ,CURLINFO_HTTP_CODE);

curl_close($ch);
fclose($fp);

print $http_code;
print "<br /><br />$http_result";
if ($error) {
   print "<br /><br />$error";
}

?>

The server responds with:

* About to connect() to localhost port 8080 (#0)
*   Trying ::1... * connected
* Connected to localhost (::1) port 8080 (#0)
> PUT /ehcache/rest/sampleCache2/3 HTTP/1.1
Host: localhost:8080
Accept: */*
Content-Length: 11
Expect: 100-continue

< HTTP/1.1 100 Continue
< HTTP/1.1 201 Created
< Location: http://localhost:8080/ehcache/rest/sampleCache2/3
< Content-Length: 0
< Server: Jetty(6.1.10)
<
* Connection #0 to host localhost left intact
* Closing connection #0

41.3 Creating Massive Caches with Load Balancers and PartitioningContents

The RESTful Ehcache Server is designed to achieve massive scaling using data partitioning - all from a RESTful interface. The largest Ehcache single instances run at around 20GB in memory. The largest disk stores run at 100Gb each. Add nodes together, with cache data partitioned across them, to get larger sizes. 50 nodes at 20GB gets you to 1 Terabyte.

Two deployment choices need to be made:

These choices can be mixed and matched with a number of different deployment topologies.

41.3.1 Non-redundant, Scalable with client hash-based routingContents

images/loadbalancer_client_hashing_nonredundant

This topology is the simplest. It does not use a load balancer. Each node is accessed directly by the cache client using REST. No redundancy is provided.

The client can be implemented in any language because it is simply a HTTP client.

It must work out a partitioning scheme. Simple key hashing, as used by memcached, is sufficient.

Here is a Java code sample:

String[] cacheservers = new String[]{"cacheserver0.company.com", "cacheserver1.company.com",
    "cacheserver2.company.com", "cacheserver3.company.com", "cacheserver4.company.com",
    "cacheserver5.company.com"};
Object key = "123231";
int hash = Math.abs(key.hashCode());
int cacheserverIndex = hash % cacheservers.length;
String cacheserver = cacheservers[cacheserverIndex];

41.3.2 Redundant, Scalable with client hash-based routingContents

images/loadbalancer_client_hashing

Redundancy is added as shown in the above diagram by: Replacing each node with a cluster of two nodes. One of the existing distributed caching options in Ehcache is used to form the cluster. Options in Ehcache 1.5 are RMI and JGroups-based clusters. Ehcache-1.6 will add JMS as a further option. Put each Ehcache cluster behind VIPs on a load balancer.

41.3.3 Redundant, Scalable with load balancer hash-based routingContents

images/loadbalancer_hashing

Many content-switching load balancers support URI routing using some form of regular expressions.

So, you could optionally skip the client-side hashing to achieve partitioning in the load balancer itself.

For example:

 /ehcache/rest/sampleCache1/[a-h]* => cluster1
 /ehcache/rest/sampleCache1/[i-z]* => cluster2

Things get much more sophisticated with F5 load balancers, which let you create iRules in the TCL language. So rather than regular expression URI routing, you could implement key hashing-based URI routing. Remember in Ehcache's RESTful server, the key forms the last part of the URI. e.g. In the URI http://cacheserver.company.com/ehcache/rest/sampleCache1/3432 , 3432 is the key.

You hash using the last part of the URI.

See http://devcentral.f5.com/Default.aspx?tabid=63&PageID=153&ArticleID=135&articleType=ArticleView for how to implment a URI hashing iRule on F5 load balancers.

41.4 W3C (SOAP) Web ServicesContents

The W3C (http://www.w3.org/ is a standards body that defines Web Services as

The World Wide Web is more and more used for application to application communication.
The programmatic interfaces made available are referred to as Web services.

They provide a set of recommendations for achieving this. See http://www.w3.org/2002/ws/.

An interoperability organisation, WS-I http://www.ws-i.org/, seeks to achieve interoperabilty between W3C Web Services. The W3C specifications for SOAP and WSDL are required to meet the WS-I definition.

Ehcache is using Glassfish's libraries to provide it's W3C web services. The project known as Metro follows the WS-I definition.

Finally, OASIS (http://oasis-open.org), defines a Web Services Security specification for SOAP: WS-Security. The current version is 1.1. It provides three main security mechanisms: ability to send security tokens as part of a message, message integrity, and message confidentiality.

Ehcache's W3C Web Services support the stricter WS-I definition and use the SOAP and WSDL specfications.

Specifically:

41.4.1 W3C Web Services APIContents

The Ehcache RESTFul Web Services API exposes the singleton CacheManager, which typically has been configured in ehcache.xml or an IoC container. Multiple CacheManagers are not supported.

The API definition is as follows:

41.4.2 SecurityContents

By default no security is configured. Because it is simply a Servlet 2.5 web application, it can be secured in all the usual ways by configuration in the web.xml.

In addition the cache server supports the use of XWSS 3.0 to secure the Web Service. See https://xwss.dev.java.net/. All required libraries are packaged in the war for XWSS 3.0.

A sample, commented out server_security_config.xml is provided in the WEB-INF directory. XWSS automatically looks for this configuration file.

A simple example, based on an XWSS example, net.sf.ehcache.server.soap.SecurityEnvironmentHandler, which looks for a password in a System property for a given username is included. This is not recommended for production use but is handy when you are getting started with XWSS.

To use XWSS:

Add configuration in accordance with XWSS to the server_security_config.xml file. Create a class which implements the CallbackHandler interface and provide its fully qualified path in the SecurityEnvironmentHandler element.

The integration test EhcacheWebServiceEndpoint test shows how to use the XWSS client side. On the client side, configuration must be provided in a file called client_security_config.xml must be in the root of the classpath.

To add client credentials into the SOAP request do:

cacheService = new EhcacheWebServiceEndpointService().getEhcacheWebServiceEndpointPort();
//add security credentials
((BindingProvider)cacheService).getRequestContext().put(BindingProvider.USERNAME_PROPERTY,
 "Ron");
((BindingProvider)cacheService).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY,
 "noR");
String result = cacheService.ping();

41.5 RequirementsContents

41.5.1 JavaContents

Java 5 or 6

41.5.2 Web Container (WAR packaged version only)Contents

The standalone server comes with its own embedded Glassfish web container.

The web container must support the Servlet 2.5 specification.

The following web container configuration have been tested:

41.6 DownloadingContents

The server is available as follows:

41.6.1 SourceforgeContents

Download here.

There are two tarball archives in tar.gz format:

41.6.2 MavenContents

The Ehcache Server is in the central Maven repository packaged as type war. Use the following Maven pom snippet:

   <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache-server</artifactId>
        <version>enter_version_here</version>
        <type>war</type>
   </dependency>

It is also available as a jaronly version, which makes it easier to embed. This version excludes all META-INF and WEB-INF configuration files, and also excludes the ehcache.xml. You need to provide these in your maven project.

    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache-server</artifactId>
        <version>enter_version_here</version>
        <type>jar</type>
        <classifier>jaronly</classifier>
   </dependency>

41.7 InstallationContents

41.7.1 Installing the WARContents

Use your Web Container's instructions to install the WAR or include the WAR in your project with Maven's war plugin.

Web Container specific configuration is provided in the WAR as follows:

41.7.2 Configuring the Web ApplicationContents

Expand the WAR.

Edit the web.xml.

41.7.2.1 Disabling the RESTful Web Service

Comment out the RESTful web service section.

41.7.2.2 Disabling the SOAP Web Service

Comment out the RESTful web service section.

41.7.2.3 Configuring Caches

The ehcache.xml configuration file is located in WEB-INF/classes/ehcache.xml.

Follow the instructions in this config file, or the core Ehcache instructions to configure.

41.7.2.4 SOAP Web Service Security

41.8 Installing the Standalone ServerContents

The WAR also comes packaged with a standalone server, based on Glassfish V3 Embedded.

The quick start is:

41.8.1 Configuring the Standalone ServerContents

Configuration is by editing the war/web.xml file as per the instructions for the WAR packaging.

41.8.2 Starting and Stopping the Standalone ServerContents

41.8.2.1 Using Commons Daemon jsvc

jsvc creates a daemon which returns once the service is started. jsvc works on all common Unix-based operating systems including Linux, Solaris and Mac OS X.

It creates a pid file in the pid directory.

This is a Unix shell script that starts the server as a daemon.

To use jsvc you must install the native binary jsvc from the Apache Commons Daemon project. The source for this is distributed in the bin directory as jsvc.tar.gz. Untar it and follow the instructions for building it or download a binary from the Commons Daemon project.

Convenience shell scripts are provided as follows:

start - daemon_start.sh

stop - daemon_stop.sh

jsvc is designed to integrate with Unix System 5 initialization scripts. (/etc/rc.d)

You can also send Unix signals to it. Meaningful ones for the Ehcache Standalone Server are:

No Meaning
1 HUP
2 INT
9 KILL
15 TERM

41.8.2.2 Executable jar

The server is also packaged as an executable jar for developer convenience which will work on all operating systems.

A convenience shell script is provided as follows:

start - startup.sh

From the bin directory you can also invoke the following command directly:

    unix    - java -jar ../lib/ehcache-standalone-server-0.7.jar 8080 ../war
    windows - java -jar ..\lib\ehcache-standalone-server-0.7.jar 8080 ..\war

41.9 MonitoringContents

The CacheServer registers Ehcache MBeans with the platform MBeanServer.

Remote monitoring of the MBeanServer is the responsibility of the Web Container or Application Server vendor.

For example, some instructions for Tomcat are here: https://wiki.internet2.edu/confluence/display/CPD/Monitoring+Tomcat+with+JMX

See your Web Container documentation for how to do this for your web container.

41.9.1 Remotely Monitoring the Standalone Server with JMXContents

The standalone server automatically exposes the MBeanServer on a port 1 higher than the HTTP listening port.

To connect with JConsole simply fire up JConsole, enter the host in the Remote field and portIn the above example that is

192.168.1.108:8686

Then click Connect.

To see the Ehcache MBeans, click on the Mbeans tab and expand the net.sf.ehcache tree node.

You will see something like the following.

images/JConsoleExample

CacheStatistics MBeans in JConsole

Of course, from there you can hook the Cache Server up to your monitoring tool of choice. See the chapter on JMX Management and Monitoring for more information.

41.10 DownloadContents

Download the ehcache-standalone-server from http://sourceforge.net/projects/ehcache/files/ehcache-server. --- Explicit Locking API ---

42 Explicit Locking APIContents

43 %toc|fromDepth=2|toDepth=2Contents

This package contains an implementation of an Ehcache which provides for explicit locking, using READ and WRITE locks.

It is possible to get more control over Ehcache's locking behaviour.

This initial version works with Ehcache when used with the Terracotta Server Array.

43.1 Locking ModesContents

43.1.1 Standalone EhcacheContents

In standalone ehcache core, there is no locking. The last write wins. This is akin to the READ_UNCOMMITTED isolation level.

43.1.2 Standard Ehcache clustered with TerracottaContents

In this case the cache is always coherent, akin to READ_COMMITTED isolation level. This package simply gives you more control over when locks are acquired and released. In regular Ehcache if you get an object to read or write it can be changed underneath you while you are performing your application level operations on the object. p/

43.1.3 Explicit Locking Ehcache clustered with TerracottaContents

With this module you can first get the lock for the key, then perform your app level operations preventing anyone else from writing to the object. When the app level operations are completed you put the Element back in the cache and release the lock so that others can now access it.

43.2 How it worksContents

A READ lock does not prevent other READers from also acquiring a READ lock and reading. A READ lock cannot be obtained if there is an oustanding WRITE lock - it will queue.

A WRITE lock cannot be obtained while there are outstanding READ locks - it will queue.

In each case to avoid locking problems, the lock should be released after use. The lock release should be in a prefinally/pre block.

If before each read, you acquire a READ lock and then before each write you acquire a WRITE lock, then an isolation level akin to READ_COMMITTED is achieved.

43.3 How to ScaleContents

Configuring each Hibernate instance with a standalone ehcache will dramatically improve performance. However most production applications use multiple application instances for redundancy and for scalability. Ideally applications are horizontally scalable, where adding more application instances linearly improves throughput.

With an application deployed on multiple nodes, using standalone Ehcache means that each instance holds its own data. On a cache miss on any node, Hibernate will hit the database. As each new node gets added database workload goes up. The solution is to turn on distributed caching.

Ehcache comes with replicated caching via RMI, JGroups or JMS. These replicate without locking and are suitable for databas offload. Generally session.refresh() should be used to check the cache against the database before performing a write that must be correct. Secondly, as each node stores all data, the cache size is limited to a comfortable storage size. Memory size is usually limited by garbage collection. Disk can also be used, but the graphs are serialized which adds overhead and results in duplication in the deserialized object graphs.

Ehcache is also the caching API to the Terracotta Server Array. Reads and writes use cluster wide locks, so when using read write Hibernate caches, the cache data on all nodes will be correct, and it is not necessary to call session.refresh().

Ehcache EX, using a single or redundant Terracotta Server Array server can comfortably store approximately 20GB per stripe. The maxElementsInMemory cache setting is used to apportion a percentage of that in process for added performance, it does not limit the size. Using striping which comes with Ehcache FX, terabyte sized caches are possible. It is possible to cache the entire database with a resulting large database offload.

These scaling decisions can be deferred. The plugin is the same regardless of how it is configured. The optimal deployment can thus be determined during performance testing or based on production experience. Finally a new application can scale as it's use grows without expensive re-architecting.

43.4 DownloadContents

The Explicit Locking API is in the ehcache-explicitlocking module. Download here.

This feature currently only works with Terracotta Server Array. It needs ehcache-core and ehcache-terracotta. which can be downloaded here.

The open source Terracotta Server Array kit (which includes ehcache-core and ehcache-terracotta) can be downloaded here. Terracotta Community Login Required

--- Write-through and Write-behind Caching with the CacheWriter ---

44 Write-through and Write-behind Caching with the CacheWriterContents

New feature in Ehcache 2.0 Write-through caching is a caching pattern where writes to the cache cause writes to an underlying resource. The cache acts as a facade to the underlying resource. With this pattern, it often makes sense to read through the cache too.

Write-behind caching uses the same client API, however the write happens asynchronously.

Ehcache-2.0 introduces write-through and write-behind caching.

While any resource can sit behind the facade of a w-t cache, such as a file system, or a web service client, the common one is a database. To simplify the discussion, we will use database as the example resource.

44.1 Potential Benefits of Write-BehindContents

The big potential benefit of write-behind is database offload. This can be achieved in a number of ways:

44.2 Limitations & Constraints of Write-BehindContents

44.2.1 Transaction BoundariesContents

If the cache participates in a JTA transaction (ehcache-2.0 and higher) (i.e. it is an XAResource) then the Cache can be made consistent with the database as the write to the database and commit or rollback happens with the transaction boundary.

In write-behind, the write to the resource happens after the write to the cache. The transaction boundary is the write to the outstanding queue, not the write behind. In write-through mode, commit can get called and both the Cache and the underlying resource, e.g. the database can get committed at once.

Because the database is being written to outside of the transaction, there is always a risk that a failure on the eventual write will occur. While this can be mitigated with retry counts and delays, compensating actions may be required.

44.2.2 Time delayContents

The obvious implication of asynchronous writes is that there is a delay between when the cache is updated and when the database is updated. This introduces an inconsistency between the cache and the database, where the cache holds the correct value and the database will be eventually consistent with the cache. The data passed into the CacheWriter methods is a snapshot of the cache entry at the time of the write to operation.

A read against the database will result in incorrect data being loaded.

44.2.3 Applications Tolerant of InconsistencyContents

The application must be tolerant of this inconsistency, as per the following are examples:

Note that in practice, if other applications are writing to the database, then a cache can often be inconsistent with the database.

44.2.4 Node time synchronisationContents

Ideally node times should be synchronised. The write-behind queue is generally written to the underlying resource in timestamp order, based on the timestamp of the cache operation, although there is no guaranteed ordering.

The ordering will be more consistent if all nodes are using the same time. This can easily be achieved by configuring your system clock to synchronise with a time authority using Network Time Protocol.

44.2.5 No ordering guaranteesContents

The items on the write-behind queue are generally in order, but this isn't guaranteed. In certain situation and more particularly in clustered usage, the items can be processed out of order. Additionally, when batching is used, write and delete collections are aggregated separately and can be processed inside the CacheWriter in a different order that the order that was used by the queue.

Your application must of tolerant for item reordering or you need to compensate for this in your implementation of the CacheWriter. Possible examples here are:

44.3 Using a combined Read-Through and Write-Behind CacheContents

For applications that are not tolerant of inconsistency, the simplest solution is for the application to always read through the same cache that it writes through. Provided all database writes are through the cache, consistency is guaranteed. And in the distributed caching scenario, using Terracotta clustering extends the same guarantee to the cluster.

If using transactions, the cache is the XAResource, and a commit is a commit to the cache.

The cache effectively becomes the System Of Record ("SOR"). Terracotta provides HA and durability and can easily act as the SOR. The database then becomes a backup to the SOR.

There are some practical problems that come up when using this approach: caching of a partial dataset and expiry and eviction limitations

44.3.1 Lazy LoadingContents

The question arises: Does the entire data set need to be loaded in the cache on startup? The answer is no, because a read-through cache uses a CacheLoader which loads data into the cache on demand. In this way the cache be populated lazily.

44.3.2 Caching of a Partial DatasetContents

If the entire dataset cannot fit in the cache, then some reads will miss the cache and fall through to the CacheLoader which will in turn hit the database. If a write has occurred but has not yet hit the database due to write-behind, then the database will be inconsistent.

The simplest solution is to ensure that the entire dataset is in the cache. This then places some implications on cache configuration in the areas of expiry and eviction.

44.3.2.1 Eviction

Eviction occurs when the maximum elements for the cache have been exceeded. Ensure that the maxElementsInMemory and, if using the DiskStore or Terracotta clustering, the maxElementsOnDisk exceeds the required size, so that eviction does not not occur.

44.3.2.2 Expiry

Even if all of the dataset can fit in the cache, it could be evicted if Elements expire. Accordingly, both timeToLive and timeToIdle should be set to eternal to prevent this from happening.

44.4 Ehcache VersionsContents

Both Ehcache standalone and with Terracotta Server Array (Ehcache EX and FX) are supported.

44.4.1 Ehcache DX (Standalone Ehcache)Contents

The write-behind queue is stored locally in memory. It supports all configuration options, but any data in the queue will be lost on JVM shutdown.

44.4.2 Ehcache EX and FXContents

44.4.2.1 Durable HA write-behind Queue

EX and FX when used with the Terracotta Server Array will store the queue on the Terracotta Server Array and can thus be configured for durability and HA. The data is still kept in the originating node for performance.

44.4.2.2 Cluster wide queue processing

In a cluster each node will have a CacheWriter configured. These will process their local work, but if there is no local work, they will poll the other nodes to see if there is outstanding work and process part of that work.

This means that workload is balanced across the cluster, and that the write-behind queue will be serviced as long as there is one Ehcache L1 instance in the cluster.

44.5 ConfigurationContents

There are many configuration options. See the CacheWriterConfiguration for properties that may be set and their effect.

Below is an example of how to configure the cache writer in XML:

<cache name="cacheName" eternal="false" maxElementsInMemory="1000" overflowToDisk="false">
    <cacheWriter writeMode="write_behind" maxWriteDelay="8" rateLimitPerSecond="5"
                 writeCoalescing="true" writeBatching="true" writeBatchSize="20"
                 retryAttempts="2" retryAttemptDelaySeconds="2">
        <cacheWriterFactory class="com.company.MyCacheWriterFactory"
                            properties="just.some.property=test; another.property=test2" propertySeparator=";"/>
    </cacheWriter>
</cache>

Further examples:

<cache name="writeThroughCache1" eternal="false" maxElementsInMemory="1000" overflowToDisk="false"/>

<cache name="writeThroughCache2" eternal="false" maxElementsInMemory="1000" overflowToDisk="false">
  <cacheWriter/>
</cache>

<cache name="writeThroughCache3" eternal="false" maxElementsInMemory="1000" overflowToDisk="false">
  <cacheWriter writeMode="write_through" notifyListenersOnException="true" maxWriteDelay="30"
               rateLimitPerSecond="10" writeCoalescing="true" writeBatching="true" writeBatchSize="8"
               retryAttempts="20" retryAttemptDelaySeconds="60"/>
</cache>

<cache name="writeThroughCache4" eternal="false" maxElementsInMemory="1000" overflowToDisk="false">
  <cacheWriter writeMode="write_through" notifyListenersOnException="false" maxWriteDelay="0"
               rateLimitPerSecond="0" writeCoalescing="false" writeBatching="false" writeBatchSize="1"
               retryAttempts="0" retryAttemptDelaySeconds="0">
      <cacheWriterFactory class="net.sf.ehcache.writer.WriteThroughTestCacheWriterFactory"/>
  </cacheWriter>
</cache>

<cache name="writeBehindCache5" eternal="false" maxElementsInMemory="1000" overflowToDisk="false">
  <cacheWriter writeMode="write-behind" notifyListenersOnException="true" maxWriteDelay="8" rateLimitPerSecond="5"
               writeCoalescing="true" writeBatching="false" writeBatchSize="20"
               retryAttempts="2" retryAttemptDelaySeconds="2">
      <cacheWriterFactory class="net.sf.ehcache.writer.WriteThroughTestCacheWriterFactory"
                          properties="just.some.property=test; another.property=test2" propertySeparator=";"/>
  </cacheWriter>
</cache>

This configuration can also be achieved through the Cache constructor in Java, like this:

Cache cache = new Cache(
     new CacheConfiguration("cacheName", 10)
     .cacheWriter(new CacheWriterConfiguration()
    .writeMode(CacheWriterConfiguration.WriteMode.WRITE_BEHIND)
    .maxWriteDelay(8)
    .rateLimitPerSecond(5)
    .writeCoalescing(true)
    .writeBatching(true)
    .writeBatchSize(20)
    .retryAttempts(2)
    .retryAttemptDelaySeconds(2)
    .cacheWriterFactory(new CacheWriterConfiguration.CacheWriterFactoryConfiguration()
        .className("com.company.MyCacheWriterFactory")
        .properties("just.some.property=test; another.property=test2")
        .propertySeparator(";"))));

Instead of relying on a CacheWriterFactoryConfiguration>> to create a <<<CacheWriter, it's also possible to explicitly register a CacheWriter instance from within Java code. This allows you to refer to local resources like database connections or file handles.

    Cache cache = manager.getCache("cacheName");
    MyCacheWriter writer = new MyCacheWriter(jdbcConnection);
    cache.registerCacheWriter(writer);

44.5.1 Configuration AttributesContents

The CacheWriterFactory supports the following attributes:

44.5.1.1 All modes

44.5.1.2 write-through mode only

44.5.1.3 write-behind mode only

44.6 APIContents

CacheLoaders are exposed for API use through the cache.getWithLoader(...) method. CacheWriters are exposed with cache.putWithWriter(...) and cache.removeWithWriter(...) methods.

For example, following is the method signature for cache.putWithWriter(...).

/**
 * Put an element in the cache writing through a CacheWriter. If no CacheWriter has been
 * set for the cache, then this method has the same effect as cache.put().
 * <p/>
 * Resets the access statistics on the element, which would be the case if it has previously
 * been gotten from a cache, and is now being put back.
 * <p/>
 * Also notifies the CacheEventListener, if the writer operation succeeds, that:
 * <ul>
 * <li>the element was put, but only if the Element was actually put.
 * <li>if the element exists in the cache, that an update has occurred, even if the element
 * would be expired if it was requested
 * </ul>
 *
 * @param element An object. If Serializable it can fully participate in replication and the
 * DiskStore.
 * @throws IllegalStateException    if the cache is not {@link net.sf.ehcache.Status#STATUS_ALIVE}
 * @throws IllegalArgumentException if the element is null
 * @throws CacheException
 */
void putWithWriter(Element element) throws IllegalArgumentException, IllegalStateException,
 CacheException;

See the Cache JavaDoc for the complete API.

44.7 SPIContents

The Ehcache write-through SPI is the CacheWriter interface. Implementers perform writes to the underlying resource in their implementation.

/**
 * A CacheWriter is an interface used for write-through and write-behind caching to a
 * underlying resource.
 * <p/>
 * If configured for a cache, CacheWriter's methods will be called on a cache operation.
 * A cache put will cause a CacheWriter write
 * and a cache remove will cause a writer delete.
 * <p>
 * Implementers should create an implementation which handles storing and deleting to an
 * underlying resource.
 * </p>
 * <h4>Write-Through</h4>
 * In write-through mode, the cache operation will occur and the writer operation will occur
 * before CacheEventListeners are notified. If
 * the write operation fails an exception will be thrown. This can result in a cache which
 * is inconsistent with the underlying resource.
 * To avoid this, the cache and the underlying resource should be configured to participate
 * in a transaction. In the event of a failure
 * a rollback can return all components to a consistent state.
 * <p/>
 * <h4>Write-Behind</h4>
 * In write-behind mode, writes are written to a write-behind queue. They are written by a
 * separate execution thread in a configurable
 * way. When used with Terracotta Server Array, the queue is highly available. In addition
 * any node in the cluster may perform the
 * write-behind operations.
 * <p/>
 * <h4>Creation and Configuration</h4>
 * CacheWriters can be created using the CacheWriterFactory.
 * <p/>
 * The manner upon which a CacheWriter is actually called is determined by the
 * {@link net.sf.ehcache.config.CacheWriterConfiguration} that is set up for cache
 * that is using the CacheWriter.
 * <p/>
 * See the CacheWriter chapter in the documentation for more information on how to use writers.
 *
 * @author Greg Luck
 * @author Geert Bevin
 * @version $Id: $
 */
public interface CacheWriter {

    /**
     * Creates a clone of this writer. This method will only be called by ehcache before a
     * cache is initialized.
     * <p/>
     * Implementations should throw CloneNotSupportedException if they do not support clone
     * but that will stop them from being used with defaultCache.
     *
     * @return a clone
     * @throws CloneNotSupportedException if the extension could not be cloned.
     */
    public CacheWriter clone(Ehcache cache) throws CloneNotSupportedException;


    /**
     * Notifies writer to initialise themselves.
     * <p/>
     * This method is called during the Cache's initialise method after it has changed it's
     * status to alive. Cache operations are legal in this method.
     *
     * @throws net.sf.ehcache.CacheException
     */
    void init();

    /**
     * Providers may be doing all sorts of exotic things and need to be able to clean up on
     * dispose.
     * <p/>
     * Cache operations are illegal when this method is called. The cache itself is partly
     * disposed when this method is called.
     */
    void dispose() throws CacheException;

    /**
     * Write the specified value under the specified key to the underlying store.
     * This method is intended to support both key/value creation and value update for a
     * specific key.
     *
     * @param element the element to be written
     */
    void write(Element element) throws CacheException;

    /**
     * Write the specified Elements to the underlying store. This method is intended to
     * support both insert and update.
     * If this operation fails (by throwing an exception) after a partial success,
     * the convention is that entries which have been written successfully are to be removed
     * from the specified mapEntries, indicating that the write operation for the entries left
     * in the map has failed or has not been attempted.
     *
     * @param elements the Elements to be written
     */
    void writeAll(Collection<Element> elements) throws CacheException;


    /**
     * Delete the cache entry from the store
     *
     * @param entry the cache entry that is used for the delete operation
     */
    void delete(CacheEntry entry) throws CacheException;


    /**
     * Remove data and keys from the underlying store for the given collection of keys, if
     * present. If this operation fails * (by throwing an exception) after a partial success,
     * the convention is that keys which have been erased successfully are to be removed from
     * the specified keys, indicating that the erase operation for the keys left in the collection
     * has failed or has not been attempted.
     *
     * @param entries the entries that have been removed from the cache
     */
    void deleteAll(Collection<CacheEntry> entries) throws CacheException;
}

--- OpenJPA Caching Provider ---

45 OpenJPA Caching ProviderContents

Ehcache easily integrates with the OpenJPA persistence framework.

45.1 InstallingContents

To use it, add a Maven dependency for ehcache-openjpa.

    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache-openjpa</artifactId>
    <version>0.1</version>

or download from downloads.

45.2 ConfigurationContents

Set OpenJPAÕs openjpa.QueryCache to ehcache and openjpa.DataCacheManager to ehcache. ThatÕs it!

See http://openjpa.apache.org/builds/1.0.2/apache-openjpa-1.0.2/docs/manual/ref_guide_caching.html for more on caching in OpenJPA.

45.3 Default CacheContents

As with Hibernate, Ehcache's OpenJPA module (from 0.2) uses the defaultCache configured in ehcache.xml to create caches.

For production, we recommend configuring a cache configuration in ehcache.xml for each cache, so that it may be correctly tuned.

--- Grails: Using Ehcache as a Second Level Caching Provider for Hibernate within Grails ---

46 Grails: Using Ehcache as a Second Level Caching Provider for Hibernate within GrailsContents

Grails 1.2RC1 and higher use Ehcache as the default Hibernate second level cache. However earlier versions of Grails ship with the Ehcache library and are very simple to enable.

The following steps show how to configure Grails to use Ehcache. For 1.2RC1 and higher some of these steps are already done for you.

46.1 Configuring Ehcache as the second level Hibernate cacheContents

Edit DataSource.groovy as follows:

    hibernate {
    cache.use_second_level_cache=true
    cache.use_query_cache=true
    cache.provider_class='org.hibernate.cache.EhCacheProvider'
}

46.2 Overriding defaults by specifying cache configurationsContents

As is usual with Hibernate, it will use the defaultCache configuration as a template to create new caches as required. For production use you often want to customise the cache configuration. To do so, add an ehcache.xml configuration file to the conf directory (the same directory that contains DataSource.groovy).

A sample ehcache.xml which works with the Book demo app and is good as a starter configuration for Grails is shown below:

<?xml version="1.0" encoding="UTF-8"?>

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="ehcache.xsd" >

    <diskStore path="java.io.tmpdir"/>

    <cacheManagerEventListenerFactory class="" properties=""/>


    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToLiveSeconds="120"
            overflowToDisk="false"
            diskPersistent="false"
            />

    <cache name="Book"
           maxElementsInMemory="10000"
           timeToIdleSeconds="300"
            />

    <cache name="org.hibernate.cache.UpdateTimestampsCache"
           maxElementsInMemory="10000"
           timeToIdleSeconds="300"
            />

    <cache name="org.hibernate.cache.StandardQueryCache"
           maxElementsInMemory="10000"
           timeToIdleSeconds="300"
            />



</ehcache>

46.3 Futher informationContents

For further information see the Hibernate chapter.

--- JSR107 (JCACHE) Support ---

47 JSR107 (JCACHE) SupportContents