EhcacheUserGuide-1 4 0
EhcacheUserGuide-1 4 0
Version 1.4.0
Greg Luck
Maintainer Ehcache
Contents
1 Preface 1.1 1.2 1.3 1.4 1.5 2 Version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Audience . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Printing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . About the ehcache name and logo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 11 11 11 11 12 13 13 13 13 13 14 14 14 15 15 15 15 16 17 17 18 19 19 19 19 20 20
Introduction 2.1 2.2 About Caches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Why caching works . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.1 2.2.2 2.3 2.3.1 2.3.2 2.3.3 2.4 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 Locality of Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Long Tail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Speeding up CPU bound Applications . . . . . . . . . . . . . . . . . . . . . . . . Speeding up I/O bound Applications . . . . . . . . . . . . . . . . . . . . . . . . . Increased Application Scalability . . . . . . . . . . . . . . . . . . . . . . . . . . The short answer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Applying Amdahls Law . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Cache Efciency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Cluster Efciency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A cache version of Amdahls law . . . . . . . . . . . . . . . . . . . . . . . . . . Web Page example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Getting Started 3.1 3.2 3.3 3.4 3.5 General Purpose Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hibernate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Java EE Servlet Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JCache style caching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Spring, Cocoon, Acegi and other frameworks . . . . . . . . . . . . . . . . . . . . . . . . 1
Features 4.1 Fast and Light Weight . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.1 4.1.2 4.1.3 4.1.4 4.2 4.2.1 4.2.2 4.2.3 4.2.4 4.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.4 4.5 4.4.1 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6 4.6.1 4.6.2 4.7 4.7.1 4.7.2 4.8 4.9 Fast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Small foot print . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Minimal dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Provides Memory and Disk stores for scalabilty into gigabytes . . . . . . . . . . . Scalable to hundreds of caches . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tuned for high concurrent load on large multi-cpu servers . . . . . . . . . . . . . Multiple CacheManagers per virtual machine . . . . . . . . . . . . . . . . . . . . Supports Object or Serializable caching . . . . . . . . . . . . . . . . . . . . . . . Support cache-wide or Element-based expiry policies . . . . . . . . . . . . . . . . Provides LRU, LFU and FIFO cache eviction policies . . . . . . . . . . . . . . . Provides Memory and Disk stores . . . . . . . . . . . . . . . . . . . . . . . . . . Distributed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Full implementation of JSR107 JCACHE API . . . . . . . . . . . . . . . . . . . . Listeners may be plugged in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Peer Discovery, Replicators and Listeners may be plugged in . . . . . . . . . . . . Cache Extensions may be plugged in . . . . . . . . . . . . . . . . . . . . . . . . Cache Loaders may be plugged in . . . . . . . . . . . . . . . . . . . . . . . . . . Cache Exception Handlers may be plugged in . . . . . . . . . . . . . . . . . . . . Persistent disk store which stores data between VM restarts . . . . . . . . . . . . Flush to disk on demand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . CacheManager listeners . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Cache event listeners . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21 23 23 24 24 24 24 24 24 24 24 24 24 25 25 25 25 25 25 25 25 25 26 26 26 26 26 26 26 26 26 27 27 27 27 27 27 27 27 28
Scalable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Complete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Application Persistence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Listeners . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
JMX Enabled . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Distributed Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 4.9.6 4.9.7 Peer Discovery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Reliable Delivery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Synchronous Or Asynchronous Replication . . . . . . . . . . . . . . . . . . . . . Copy Or Invalidate Replication . . . . . . . . . . . . . . . . . . . . . . . . . . . Transparent Replication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Extensible . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Bootstrapping from Peers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
4.10 Java EE and Applied Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.10.1 Blocking Cache to avoid duplicate processing for concurrent operations . . . . . . 4.10.2 SelfPopulating Cache for pull through caching of expensive operations . . . . . . 4.10.3 Java EE Gzipping Servlet Filter . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.10.4 Cacheable Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.10.5 Works with Hibernate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.11 High Quality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.11.1 High Test Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.11.2 Automated Load, Limit and Performance System Tests . . . . . . . . . . . . . . . 4.11.3 Specic Concurrency Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.11.4 Production tested . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.11.5 Fully documented . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.11.6 Trusted by Popular Frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.11.7 Conservative Commit policy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.11.8 Full public information on the history of every bug . . . . . . . . . . . . . . . . . 4.11.9 Responsiveness to serious bugs . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.12 Open Source Licensing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.12.1 Apache 2.0 license . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Key Ehcache Concepts 5.1 Key Ehcache Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.1 5.1.2 5.1.3 5.2 5.2.1 5.2.2 6 CacheManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ehcache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Element . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Direct Manipulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Self Populating . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
28 28 28 28 28 29 29 29 29 29 29 30 30 30 30 30 30 30 31 31 32 34 35 36 36 36 37 37 40 40 49 49 49 50 53 53 53
Cache Conguration 6.1 6.2 6.3 ehcache.xsd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ehcache-failsafe.xml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ehcache.xml and other conguration les . . . . . . . . . . . . . . . . . . . . . . . . . .
Storage Options 7.1 7.2 Memory Store . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.1.1 Memory Use, Spooling and Expiry Strategy . . . . . . . . . . . . . . . . . . . . . DiskStore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Cache Eviction Algorithms 8.1 Eviction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.1 Supported MemoryStore Eviction Algorithms . . . . . . . . . . . . . . . . . . . 3
8.1.2 8.1.3 9
53 54 55 55 56 56 56 57 57 57 57 58 58 59 59 59 60 60 61 61 61 61 61 62 62 62 62 63 63 63 64 65 65 65 66 67
. . . . . . . . . . . . . . . . . . . . . . . . . .
Code Samples 9.1 Using the CacheManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.1.1 9.1.2 9.1.3 9.1.4 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3 9.4 9.5 9.6 Singleton versus Instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ways of loading Cache Conguration . . . . . . . . . . . . . . . . . . . . . . . . Adding and Removing Caches Programmatically . . . . . . . . . . . . . . . . . . Shutdown the CacheManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obtaining a reference to a Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . Performing CRUD operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . Disk Persistence on demand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obtaining Cache Sizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obtaining Statistics of Cache Hits and Misses . . . . . . . . . . . . . . . . . . . .
Using Caches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Creating a new cache from defaults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a new cache with custom parameters . . . . . . . . . . . . . . . . . . . . . . . . Registering CacheStatistics in an MBeanServer . . . . . . . . . . . . . . . . . . . . . . . Browse the JUnit Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10 Java Requirements, Dependencies and Maven POM snippet 10.1 Java Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2 Mandatory Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2.1 Commons Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2.2 Backport Concurrent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3 Optional Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3.1 JMX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3.2 Commons collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.4 Maven pom.xml snippet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Logging And Debugging 11.1 Commons Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 Logging Philosophy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.3 Remote Network debugging and monitoring for Distributed Caches . . . . . . . . . . . . 12 Garbage Collection 12.1 Detecting Garbage Collection Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2 Garbage Collection Tuning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.3 Distributed Caching Garbage Collection Tuning . . . . . . . . . . . . . . . . . . . . . . . 13 JMX Management and Monitoring 4
13.1 JMX Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.2 Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.3 MBeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.4 JMX Remoting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.5 ObjectName naming scheme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.6 The Management Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.7 JConsole Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.8 JMX Tutorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Class loading and Class Loaders 14.1 Plugin class loading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.2 Loading of ehcache.xml resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Performance Considerations 15.1 DiskStore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.2 Replication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Cache Decorators 16.1 Creating a Decorator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.2 Accessing the decorated cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.2.1 Using CacheManager to access decorated caches . . . . . . . . . . . . . . . . . . 16.3 Built-in Decorators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.3.1 BlockingCache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.3.2 SelfPopulatingCache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.3.3 Caches with Exception Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Shutting Down Ehcache 17.1 The shutdown hook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17.2 When to use the shutdown hook . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17.3 What the shutdown hook does . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17.4 When a shutdown hook will run, and when it will not . . . . . . . . . . . . . . . . . . . . 17.5 If ehcache is shutdown dirty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Java EE Servlet Caching 18.1 CachingFilter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18.2 SimplePageCachingFilter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18.3 PageFragmentCachingFilter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18.4 SimplePageFragmentCachingFilter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 The Design of distributed ehcache 19.1 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.2 Problems with Instance Caches in a Clustered Environment . . . . . . . . . . . . . . . . . 5
67 68 68 68 68 68 70 70 71 71 72 73 73 73 75 75 75 75 76 76 77 78 79 79 79 79 80 80 81 81 81 82 82 83 83 83
19.3 Replicated Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.4 Distributed Cache Terms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.5 Notication Strategies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.6 Topology Choices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.6.1 Peer Cache Replicator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.6.2 Centralised Cache Replicator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.7 Discovery Choices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.7.1 Multicast Discovery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.7.2 Static List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.8 Delivery Mechanism Choices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.8.1 Custom Socket Protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.8.2 Multicast Delivery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.8.3 JMS Topics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.8.4 RMI RMI is the default RPC mechanism in Java. . . . . . . . . . . . . . . . . . . 19.8.5 JXTA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.8.6 JGroups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.8.7 The Default Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.9 Replication Drawbacks and Solutions in ehcaches implementation . . . . . . . . . . . . . 19.9.1 Chatty Protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.9.2 Redundant Notications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.9.3 Potential for Inconsisent Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.9.4 Synchronous Delivery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.9.5 Update via Invalidation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Distributed Caching 20.1 Suitable Element Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.2 Peer Discovery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.2.1 Automatic Peer Discovery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.2.2 Manual Peer Discovery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.3 Conguring a CacheManagerPeerListener . . . . . . . . . . . . . . . . . . . . . . . . . . 20.4 Conguring CacheReplicators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.5 Common Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.5.1 Tomcat on Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.5.2 Multicast Blocking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.5.3 Multicast Not Progagating Far Enough or Propagating Too Far . . . . . . . . . . . 21 The Design of the ehcache constructs package 21.1 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.2 The purpose of the Constructs package . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.3 Caching meets Concurrent Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
83 84 84 84 84 84 84 84 85 85 85 85 85 85 85 85 85 86 86 86 86 87 87 89 89 89 90 90 91 92 92 92 93 93 95 95 95 95
21.4 What can possibly go wrong? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.4.1 Safety Failures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.4.2 Liveness Failures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.5 The constructs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.5.1 Blocking Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.5.2 SelfPopulatingCache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.5.3 CachingFilter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.5.4 SimplePageCachingFilter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.5.5 PageFragmentCachingFilter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.5.6 SimplePageFragmentCachingFilter . . . . . . . . . . . . . . . . . . . . . . . . . 21.5.7 AsynchronousCommandExecutor . . . . . . . . . . . . . . . . . . . . . . . . . . 21.6 Real-life problems in the constructs package and their solutions . . . . . . . . . . . . . . . 21.6.1 The Blocking Cache Stampede . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.6.2 The Blank Page problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
96 96 96 96 96 98 98 98 98 99 99 99 99 99
22.1 Conguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 22.2 Implementing a CacheManagerEventListenerFactory and CacheManagerEventListener . . 102 23 Cache Loaders 105
23.1 Declarative Conguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 23.2 Implementing a CacheLoaderFactory and CacheLoader . . . . . . . . . . . . . . . . . . . 106 23.3 Programmatic Conguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 24 Cache Event Listeners 109
24.1 Conguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 24.2 Implementing a CacheEventListenerFactory and CacheEventListener . . . . . . . . . . . 110 25 Cache Exception Handlers 113
25.1 Declarative Conguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 25.2 Implementing a CacheExceptionHandlerFactory and CacheExceptionHandler . . . . . . . 113 25.3 Programmatic Conguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 26 Cache Extensions 117
26.1 Declarative Conguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 26.2 Implementing a CacheExtensionFactory and CacheExtension . . . . . . . . . . . . . . . . 117 26.3 Programmatic Conguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 27 Hibernate Caching 121
27.1 Setting ehcache as the cache provider . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 27.1.1 Using the ehcache provider from the ehcache project . . . . . . . . . . . . . . . . 121 7
27.1.2 Using the ehcache provider from the Hibernate project . . . . . . . . . . . . . . . 122 27.1.3 Programmatic setting of the Hibernate Cache Provider . . . . . . . . . . . . . . . 122 27.2 Hibernate Mapping Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 27.2.1 read-write . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 27.2.2 nonstrict-read-write . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 27.2.3 read-only . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 27.3 Hibernate Doclet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 27.4 Conguration with ehcache.xml . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 27.4.1 Domain Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 27.4.2 Hibernate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 27.4.3 Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 27.4.4 Hibernate CacheConcurrencyStrategy . . . . . . . . . . . . . . . . . . . . . . . . 125 27.4.5 Queries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 27.4.6 StandardQueryCache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 27.4.7 UpdateTimestampsCache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 27.4.8 Named Query Caches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 27.4.9 Using Query Caches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 27.4.10 Hibernate CacheConcurrencyStrategy . . . . . . . . . . . . . . . . . . . . . . . . 126 27.5 Hibernate Caching Performance Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 27.5.1 In-Process Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 27.5.2 Object Id . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 27.5.3 Session.load . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 27.5.4 Session.nd and Query.nd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 27.5.5 Session.iterate and Query.iterate . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 28 JSR107 (JCACHE) Support 129
28.1 JSR107 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 28.2 Using JCACHE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 28.2.1 Creating JCaches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 28.2.2 Getting a JCache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 28.2.3 Using a JCache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 28.3 Problems and Limitations in the early draft of JSR107 . . . . . . . . . . . . . . . . . . . . 131 28.3.1 net.sf.jsr107cache.CacheManager . . . . . . . . . . . . . . . . . . . . . . . . . . 131 28.3.2 net.sf.jsr107cache.CacheFactory . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 28.3.3 net.sf.jsr107cache.Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 28.3.4 net.sf.jsr107cache.CacheEntry . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 28.3.5 net.sf.jsr107cache.CacheStatistics . . . . . . . . . . . . . . . . . . . . . . . . . . 133 28.3.6 net.sf.jsr107cache.CacheListener . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 28.3.7 net.sf.jsr107cache.CacheLoader . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 28.4 Other Areas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 8
28.4.1 JMX
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 137
29.1 Tomcat Known Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 29.1.1 If I restart/reload a web application in Tomcat that has a CacheManager that is part of a cluster, the CacheManager is unable to rejoin the cluster. If I set logging for net.sf.ehcache.distribution to FINE I see the following exception: "FINE: Unable to lookup remote cache peer for .... Removing from peer list. Cause was: error unmarshalling return; nested exception is: java.io.EOFException. . . . . . . . . . 137 29.1.2 In development, there appear to be classloader memory leak as I continually redeploy my web application. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 29.1.3 I get net.sf.ehcache.CacheException: Problem starting listener for RMICachePeer ... java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: java.net.MalformedURLException: no protocol: Files/Apache. What is going on? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 29.1.4 Multiple Host Entries in Tomcats server.xml stops replication from occurring . . . 138 30 Building from Source 139
30.1 Building Approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 30.2 Building an ehcache distribution from source . . . . . . . . . . . . . . . . . . . . . . . . 139 30.3 Running Tests for Ehcache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 30.4 Building the Site . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 30.5 Deploying a release . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 30.5.1 Sourceforge Release . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 30.5.2 Central Maven Repository . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 31 Frequently Asked Questions 141
31.1 Does ehcache run on JDK1.3? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 31.2 Can you use more than one instance of ehcache in a single VM? . . . . . . . . . . . . . . 141 31.3 Can you use ehcache with Hibernate and outside of Hibernate at the same time? . . . . . . 141 31.4 What happens when maxElementsInMemory is reached? Are the oldest items are expired when new ones come in? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 31.5 Is it thread safe to modify Element values after retrieval from a Cache? . . . . . . . . . . . 142 31.6 Can non-Serializable objects be stored in a cache? . . . . . . . . . . . . . . . . . . . . . . 142 31.7 Why is there an expiry thread for the DiskStore but not for the MemoryStore? . . . . . . . 142 31.8 What elements are mandatory in ehcache.xml? . . . . . . . . . . . . . . . . . . . . . . . 142 31.9 Can I use ehcache as a memory cache only? . . . . . . . . . . . . . . . . . . . . . . . . . 143 31.10Can I use ehcache as a disk cache only? . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 31.11Where is the source code? The source code is distributed in the root directory of the download.143 31.12How do you get statistics on an Element without affecting them? . . . . . . . . . . . . . . 143 31.13How do you get WebSphere to work with ehcache? . . . . . . . . . . . . . . . . . . . . . 143 31.14Do you need to call CacheManager.getInstance().shutdown() when you nish with ehcache? 143 31.15Can you use ehcache after a CacheManager.shutdown()? . . . . . . . . . . . . . . . . . . 143 9
31.16I have created a new cache and its status is STATUS_UNINITIALISED. How do I initialise it? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 31.17Is there a simple way to disable ehcache when testing? . . . . . . . . . . . . . . . . . . . 144 31.18Is there a Maven bundle for ehcache? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 31.19How do I dynamically change Cache attributes at runtime? . . . . . . . . . . . . . . . . . 144 31.20I get net.sf.ehcache.distribution.RemoteCacheException: Error doing put to remote peerremote peer. Message was: Error unmarshaling return header; nested exception is: java.net.SocketTimeoutException: Read timed out. What does this mean. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 31.21Should I use this directive when doing distributed caching? cacheManagerEventListenerFactory class="" properties=""/ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 31.22What is the minimum cong to get distributed caching going? . . . . . . . . . . . . . . . 145 31.23How can I see if distributed caching is working? . . . . . . . . . . . . . . . . . . . . . . . 145 31.24Why cant I run multiple applications using ehcache on one machine? . . . . . . . . . . . 146 31.25How many threads does ehcache use, and how much memory does that consume? . . . . . 146 31.26I am using Tomcat 5, 5.5 or 6 and I am having a problem. What can I do? . . . . . . . . . 146 31.27I am using Java 6 and getting a java.lang.VerifyError on edu.emory.mathcs.backport.java.util.concurrent classes. Why? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 32 About the ehcache name and logo 147
10
Chapter 1
Preface
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, application persistence and distributed caching. The biggest issue faced by Ehcache users at the time of writing is understanding when and how to use these features.
1.1 Version
This book is for Ehcache version 1.4.0.
1.2 Audience
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 ehcaches approach to help make a decision about appropriateness of use.
1.3 Printing
The PDF is designed to be printed, with blank pages deliberately left to maintiain book conventions.
1.4 Acknowledgements
Ehcache has had many contributions in the form of forum discussions, feature requests, bug reports, patches and code commits. 11
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: Bug reports and features requests appear in the changes report here: Patch contributors generally end up with an author tag in the source they contributed to Team members appear on the team list page here: Thanks to Denis Orlov for suggesting the need for a book in the rst place.
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.
12
Chapter 2
Introduction
Ehcache is a cache library. Before getting into ehcache, it is worth stepping back and thinking about caching generally.
The Long Tail is itself a vernacular term for a Power Law probability distribution. They dont 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.
The following examples show how to apply Amdahls law to common situations. In the interests of simplicity, we assume: a single server a system with a single thing in it, which when cached, gets 100% cache hits and lives forever. 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: 15
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
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. Lets 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
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.
Server 1 M H H H H ...
Server 2 M H H H H ...
Server 3 M H H H H ...
Server 4 M H H H H ...
The cache hit ratios for the system as a whole are as follows:
Where the lifespan is large relative to the number of standalone caches, cache efciency is not much affected. However when the lifespan is short, cache efciency 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.)
* effective cac
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 efciency is 70%; a doubling of efciency. 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 efciency is 90%; a doubling of efciency. 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 Amdahls law is most sensitive to the proportion of the system that is sped up. 18
Chapter 3
Getting Started
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.2 Hibernate
Perform the same steps as General Purpose Caching. Create caches in ehcache.xml. See Hibernate Caching for more information.
Congure the web.xml. Declare the lters created above and create lter mapping associating the lter with a URL. See Java EE Servlet Caching for more information.
20
Chapter 4
Features
Fast and Light Weight Fast Simple Small foot print Minimal dependencies Scalable Provides Memory and Disk stores for scalabilty into gigabytes Scalable to hundreds of caches Tuned for high concurrent load on large multi-cpu servers Multiple CacheManagers per virtual machine Complete Supports Object or Serializable caching Support cache-wide or Element-based expiry policies Provides LRU, LFU and FIFO cache eviction policies Provides Memory and Disk stores Distributed Caching Full implementation of JSR107 JCACHE API Standards Based Full implementation of JSR107 JCACHE API Extensible Listeners may be plugged in Peer Discovery, Replicators and Listeners may be plugged in Cache Extensions may be plugged in Cache Loaders may be plugged in Cache Exception Handlers may be plugged in 21
Application Persistence Persistent disk store which stores data between VM restarts Flush to disk on demand Supports Listeners CacheManager listeners Cache event listeners JMX Enabled Distributed Peer Discovery Reliable Delivery Synchronous Or Asynchronous Replication Copy Or Invalidate Replication Transparent Replication Extensible Bootstrapping from Peers Java EE and Applied Caching Blocking Cache to avoid duplicate processing for concurrent operations SelfPopulating Cache for pull through caching of expensive operations Java EE Gzipping Servlet Filter Cacheable Commands Works with Hibernate High Quality High Test Coverage Automated Load, Limit and Performance System Tests Production tested Fully documented Trusted by Popular Frameworks Conservative Commit policy Full public information on the history of every bug Responsiveness to serious bugs Open Source Licensing Apache 2.0 license 22
ehcache-1.1 [java] [java] [java] [java] [java] [java] [java] [java] [java] [java] [java] [java] [java] [java] [java] [java] [java] [java] [java] --------------------------------------------------------------java.version=1.4.2_09 java.vm.name=Java HotSpot(TM) Client VM java.vm.version=1.4.2-54 java.vm.info=mixed mode java.vm.vendor="Apple Computer, Inc." os.name=Mac OS X os.version=10.4.5 os.arch=ppc --------------------------------------------------------------This test can take about 5-10 minutes. Please wait ... --------------------------------------------------------------|GetPutRemoveT |GetPutRemove |Get | --------------------------------------------------------------cache4j 0.4 |9240 |9116 |5556 | oscache 2.2 |33577 |30803 |8350 | ehcache 1.1 |7697 |6145 |3395 | jcs 1.2.7.0 |8966 |9455 |4072 | ---------------------------------------------------------------
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] ---------------------------------------------------------------
23
4.1.2 Simple
Many users of ehcache hardly know they are using it. Sensible defaults require no initial conguration. 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.
4.2 Scalable
4.2.1 Provides Memory and Disk stores for scalabilty into gigabytes
The largest ehcache installations use memory and disk stores in the gigabyte range. Ehcache is tuned for these large sizes.
4.3 Complete
4.3.1 Supports Object or Serializable caching
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. 24
4.3.5 Distributed
Flexible, extensible, high performance distributed caching. The default implementation supports cache discovery via multicast or manual conguration. 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.
4.5 Extensible
4.5.1 Listeners may be plugged in
Ehcache 1.2 provides CacheManagerEventListener and CacheEventListener interfaces. Implementations can be plugged in and congured in ehcache.xml.
4.7 Listeners
4.7.1 CacheManager listeners
Register Cache Manager listeners through the CacheManagerEventListener interface with the following event methods: notifyCacheAdded() notifyCacheRemoved()
4.9.6 Extensible
Distributed caching, introduced in ehcache 1.2 involves many choices and tradeoffs. The ehcache team believe that one size will not t all. Implementers can use built-in mechanisms or write their own. A plugin development guide is included for this purpose. 27
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.EhCacheP makes those additional features available to Hibernate-3.1.3. A version of the new provider should make it into the Hibernate3.2 release.
of the team that most threading issues do not surface until this type of load has been applied. Once an issue has been identied and investigated a concurrency unit test can then be crafted.
30
Chapter 5
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. 31
5.1.1 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.
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.
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 conguration. 32
If the Caches under management use only the MemoryStore, there are no special considerations. If Caches use the DiskStore, the diskStore path specied in each CacheManager conguration 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.
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. 33
5.1.2 Ehcache
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 overow to a DiskStore. 34
5.1.3 Element
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. 35
36
Chapter 6
Cache Conguration
Caches can be congured 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 conguration from runtime use. There are also these benets: It is easy if you have all of your conguration in one place. Caches consume memory, and disk space. They need to be carefully tuned. You can see the total effect in a conguration le. You could do this code, but it would not as visible. Cache conguration can be changed at deployment time. Conguration errors can be checked for at start-up, rather than causing a runtime error. This chapter covers XML declarative conguration. See the Code samples for programmatic conguration. Ehcache is redistributed by lots of projects. They may or may not provide a sample ehcache XML conguration le. If one is not provided, download ehcache from http://ehcache.sf.net. It, and the ehcache.xsd is provided in the distribution.
6.1 ehcache.xsd
Ehcache conguration les must be comply with the ehcache XML schema, ehcache.xsd, reproduced below.
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:element name="ehcache" > <xs:complexType> <xs:sequence> <xs:element ref="diskStore"/> <xs:element minOccurs="0" maxOccurs="1" ref="cacheManagerEventListenerFactory"/> <xs:element minOccurs="0" maxOccurs="1" ref="cacheManagerPeerProviderFactory"/> <xs:element minOccurs="0" maxOccurs="1" ref="cacheManagerPeerListenerFactory"/> <xs:element ref="defaultCache"/> <xs:element maxOccurs="unbounded" ref="cache"/>
37
</xs:sequence> </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> <!-- 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="1" ref="bootstrapCacheLoaderFactory"/> <xs:element minOccurs="0" maxOccurs="1" ref="cacheExceptionHandlerFactory"/> <xs:element minOccurs="0" maxOccurs="1" ref="cacheLoaderFactory"/> </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="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="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: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="1" ref="bootstrapCacheLoaderFactory"/> <xs:element minOccurs="0" maxOccurs="1" ref="cacheExceptionHandlerFactory"/>
38
<xs:element minOccurs="0" maxOccurs="1" ref="cacheLoaderFactory"/> </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="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="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: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:schema>
39
6.2 ehcache-failsafe.xml
If the CacheManager default constructor or factory method is called, ehcache looks for a le 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 conguration 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 conguration. The meaning of the elments 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" overowToDisk="true" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" / /ehcache ---
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehc <!-CacheManager Configuration ========================== An ehcache.xml corresponds to a single CacheManager. See instructions below or the ehcache schema (ehcache.xsd) on how to configure. DiskStore configuration ======================= Sets the path to the directory where cache files are created. If the path is a Java System Property it is replaced by its value in the running VM. The following properties are translated: * user.home - Users home directory * user.dir - Users current working directory * java.io.tmpdir - Default temp file path Subdirectories can be specified below the property e.g. java.io.tmpdir/one --> <diskStore path="java.io.tmpdir"/> <!--
40
CacheManagerEventListener ========================= Specifies a CacheManagerEventListenerFactory, be used to create a CacheManagerPeerProvider, 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 ======================== (Enable for distributed operation) Specifies a CacheManagerPeerProviderFactory which will be used to create a CacheManagerPeerProvider, which discovers other CacheManagers in the cluster. The attributes of cacheManagerPeerProviderFactory 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 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="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 pro By convention, the restrictions are: 0 - the same host
41
1 32 64 128 255
the same subnet the same site the same region the same continent unrestricted
Configuring Manual Discovery: Manual discovery is configured as per the following example: <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 The hostname is the hostname of the remote CacheManager peer. The port is the listening port of the RMICacheManagerPeerListener of the remote CacheManager peer. --> <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, socketTimeoutMillis=120000" propertySeparator="," /> All properties are optional. They are:
42
* 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 listener listens on. 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 120000ms. --> <cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/>
<!-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 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, 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.
43
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. 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) 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. 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 caches configuration as per the following example: <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory" properties="replicateAsynchronously=true, replicatePuts=true, 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. * 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.
44
* 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
Cluster Bootstrapping 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).
By default, most cache operations will propagate a runtime CacheException on failure. An inter using a dynamic proxy, may be configured so that a CacheExceptionHandler can be configured t intercept Exceptions. Errors are not intercepted. It is configured as per the following exam
<cacheExceptionHandlerFactory class="net.sf.ehcache.exceptionhandler.CountingExceptionHandl properties="logLevel=FINE"/> Caches with ExceptionHandling configured are not of type Cache, but are of type Ehcache only, using CacheManager.getCache(), but using CacheManager.getEhcache().
CacheLoader A CacheLoader may be configured against a cache. <cacheLoaderFactory class="net.sf.ehcache.loader.CountingCacheLoaderFactory" properties="type=int,startCounter=10"/> --> <!-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
45
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"
46
<!-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, 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. --> <cache name="sampleDistributedCache3" maxElementsInMemory="10" eternal="false" timeToIdleSeconds="100" timeToLiveSeconds="100" overflowToDisk="false">
47
</ehcache>
48
Chapter 7
Storage Options
Ehcache has two stores: a MemoryStore and a DiskStore
When an element is added to a cache and it goes beyond its maximum memory size, an existing element is either deleted, if overowToDisk is false, or evaluated for spooling to disk, if overowToDisk 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 specied in the conguration le. 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. Least Recently Used (LRU) - Default 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. 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 for the memory store) the element with least number of hits, the Less Frequently Used element, is evicted. 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 rst (First-In) in the store is the candidate for eviction (First-Out). For all the eviction policies there are also putQuiet and getQuiet methods which do not update the last used timestamp. When there is a get or a getQuiet on an element, it is checked for expiry. If expired, it is removed and null is returned. Note that at any point in time there will usually be some expired elements in the cache. Memory sizing of an application must always take into account the maximum size of each cache. There is a convenience method which can provide an estimate of the size in bytes of the MemoryStore. See calculateInMemorySize(). It returns the serialized size of the cache. Do not use this method in production. It is very slow. It is only meant to provide a rough estimate. The alternative would have been to have an expiry thread. This is a trade-off between lower memory use and short locking periods and cpu utilisation. The design is in favour of the latter. For those concerned with memory use, simply reduce the maxElementsInMemory.
7.2 DiskStore
The DiskStore provides a disk spooling facility. Suitable Element Types Only Elements which are Serializable can be placed in the DiskStore. Any non serializable Elements which attempt to overow to the DiskStore will be removed instead, and a WARNING level log message emitted. It has the following characteristics: Storage Files The disk store creates one le per cache called "cache name.data". If the DiskStore is congured to be persistent, a "cache name.index" le is also created. 50
Files are created in the directory specied by the diskStore conguration element. The default conguration is "java.io.tmpdir", which causes les to be created in the systems temporary directory. Following is a list of Java system properties which are supported as values for diskStore: user.home - Users home directory user.dir - Users current working directory java.io.tmpdir - Default temp le path Apart from these, any directory can be specied using syntax appropriate to the operating system. e.g. for Unix "/home/application/cache". Expiry Strategy 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. Eviction Strategy 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 congurable to use another algorithm. Serializable Objects Only Serializable objects can be stored in a DiskStore. A NotSerializableException will be thrown if the object is not serializable. Safety
DiskStores are thread safe.
Persistence
DiskStore persistence is controlled by the diskPersistent conguration element. If false or omitted, DiskStores will not persist between CacheManager restarts. The data le 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 le, and an index le, 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 le is updated continuously during operation of the Disk Store. New elements are spooled to disk, and deleted when expired. The index le 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: Any non-expired Elements of the MemoryStore are ushed to the DiskStore Elements awaiting spooling are spooled to the data le The free list and element list are serialized to the index le On startup the following steps take place: An attempt is made to read the index le. If it does not exist or cannot be read successfully, due to disk corruption, upgrade of ehcache, change in JDK version etc, then the data le is deleted and the DiskStore starts with no Elements in it. 51
If the index le is read successfully, the free list and element list are loaded into memory. Once this is done, the index le contents are removed. This way, if there is a dirty shutdown, when restarted, ehcache will delete the dirt index and data les. The DiskStore starts. All data is available. The expiry thread starts. It will delete Elements which have expired. These actions favour safety over persistence. Ehcache is a cache, not a database. If a le 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. Fragmentation Expiring an element frees its space on the le. This space is available for reuse by new elements. The element is also removed from the in-memory index of elements. Speed Spool requests are placed in-memory and then asynchronously written to disk. There is one thread per cache. An in-memory index of elements on disk is maintained to quickly resolve whether a key exists on disk, and if so to seek it and read it. Serialization Writes to and from the disk use ObjectInputStream and the Java serialization mechanism. This is not required for the MemoryStore. As a result the DiskStore can never be as fast as the MemoryStore. Serialization speed is affected by the size of the objects being serialized and their type. It has been found in the ElementTest test that: The serialization time for a Java object being a large Map of String arrays was 126ms, where the a serialized size was 349,225 bytes. The serialization time for a byte[] was 7ms, where the serialized size was 310,232 bytes Byte arrays are 20 times faster to serialize. Make use of byte arrays to increase DiskStore performance. RAMFS One option to speed up disk stores is to use a RAM le system. On some operating systems there are a plethora of le systems to choose from. For example, the Disk Cache has been successfully used with Linux RAMFS le system. This le system simply consists of memory. Linux presents it as a le system. The Disk Cache treats it like a normal disk - it is just way faster. With this type of le system, object serialization becomes the limiting factor to performance.
52
Chapter 8
8.1.2
MemoryStore
Eviction Algorithms
The MemoryStore supports three eviction algorithms: LRU, LFU and FIFO. The default is LRU. 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. 53
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. 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 rst (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.
8.1.3
DiskStore
Eviction Algorithms
The DiskStore uses the Less Frequently Used algorithm to evict an element when it is full.
54
Chapter 9
Code Samples
This page shows some of the more common code samples to get you started. Code samples for each feature are in the relevant chapters. Using the CacheManager Singleton versus Instance Ways of loading Cache Conguration Adding and Removing Caches Programmatically Shutdown the CacheManager Using Caches Obtaining a reference to a Cache CRUD operations Disk Persistence on demand Cache Sizes Statistics of Cache Hits and Misses Programmatically Creating Caches Creating a new cache from defaults Creating a new cache with custom parameters Registering CacheStatistics in an MBeanServer Browse the JUnit Tests
Create two CacheManagers, each with a different conguration, 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();
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 Cache#Cache(...) for the full parameters for a new Cache: Remove cache called sampleCache1
CacheManager singletonManager = CacheManager.create(); singletonManager.removeCache("sampleCache1");
Shutdown a CacheManager instance, assuming you have a reference to the CacheManager called manager
manager.shutdown();
57
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");
58
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.
59
Once the cache is created, add it to the list of caches managed by the CacheManager:
manager.addCache(testCache);
60
Chapter 10
62
Chapter 11
It will print a conguration of the cache, including replication settings and monitor the number of elements in the cache. If you are not seeing replication in your application, run up this tool to see what is going on. It is a command line application, so it can easily be run from a terminal session.
64
Chapter 12
Garbage Collection
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.
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.
The reasoning for each setting is as follows: -XX:+DisableExplicitGC - some libs call System.gc(). This is usually a bad idea and could explain some of what we saw. -XX:+UseConcMarkSweepGC - use the low pause collector -XX:NewSize=1/4 of total heap size -XX:SurvivorRatio=16 65
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.
66
Chapter 13
13.2 Dependencies
The management package of ehcache requires JMX. Version 1.3 or higher will work. This is optional and only required if you are using the ManagementService.
13.3 MBeans
Ehcache uses Standard MBeans. MBeans are available for the following: CacheManager Cache CacheConguration CacheStatistics All MBean attributes are available to a local MBeanServer. The CacheManager MBean allows traversal to its collection of Cache MBeans. Each Cache MBean likewise allows traversal to its CacheConguration MBean and its CacheStatistics MBean.
13.5
ObjectName
naming scheme
ManagementService There is only one method, ManagementService.registerMBeans which is used to initiate JMX registration of an ehcache CacheManagers instrumented MBeans. The ManagementService is a CacheManagerEventListener and is therefore notied 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 * or Cache, while CacheStatistics and CacheConfiguration are. Finally CacheManager and Cache * management operations to be performed. * <p/> * Once monitoring is enabled caches will automatically added and removed from the MBeanServe * as they are added and disposed of from the CacheManager. When the CacheManager itself shuts * 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 {
69
70
Chapter 14
71
} /** * 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.
72
Chapter 15
Performance Considerations
15.1 DiskStore
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: Serialization of the key and value Eviction from the MemoryStore using an eviction algorithm Reading from disk 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.
15.2 Replication
The asynchronous replicator is the highest performance. There are two different effects: Because it is asynchronous the caller returns immediately The messages are placed in a queue. As the queue is processed, multiple messages are sent in one RMI call, dramatically accelerating replication performance.
73
74
Chapter 16
Cache Decorators
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.
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: 75
/** * The cache holding the web pages. Ensure that all threads for a given cache name are using t */ private BlockingCache blockingCache;
/** * Initialises blockingCache to use * * @throws CacheException The most likely cause is that a cache has not been configured in ehcaches configuration file ehcache.xml for the filte * */ 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()); } } }
BlockingCache
16.3.2 SelfPopulatingCache
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. 77
SelfPopulatingCache extends BlockingCache. Multiple threads attempting to access a null element will block until the rst 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.
SelfPopulatingCache
78
Chapter 17
17.4 When a shutdown hook will run, and when it will not
The shutdown hook runs when: a program exists normally. e.g. System.exit() is called, or the last non-daemon thread exits the Virtual Machine is terminated. e.g. CTRL-C. This corresponds to kill -SIGTERM pid or kill -15 pid on Unix systems. The shutdown hook will not run when: the Virtual Machine aborts A SIGKILL signal is sent to the Virtual Machine process on Unix systems. e.g. kill -SIGKILL pid or kill -9 pid A TerminateProcess call is sent to the process on Windows systems.
80
Chapter 18
18.1 CachingFilter
You want to use the BlockingCache with web pages, but the requirement to always release the lock creates gnarly code. You also want to think about what you are doing withs involved. This is on every jsp:include and every Servlet. And you can programmatically add your own. If you have content generated by JSP, Velocity, XSLT, Servlet output or anything else, it can all be cached by CachingFilter. A separation of concerns. How do you determine what the key of a page is? The lter has an abstract calculateKey method, so it is up to you. You notice a problem and an opportunity. The problem is that the web pages you are caching are huge. That chews up either a lot of memory (Memoryout thinking about the caching. Enter the CachingFilter, a Servlet 2.3 compliant lter. Why not just do a JSP tag library, like OSCache? The answer is that you want the caching of your responses to be independent of the rendering technology. The lter chain is reexcuted every time a RequestDispatcher iStore) or a lot of disk space (DiskStore). Also you notive that these pages take their time going over the Internet. The opportunity is that you notice that all modern browsers support gzip encoding. A survey of logs reveals that 85% of the time the browser accepts gzipping. (The majority of the 15% that does not is IE behind a proxy). Ok, so gzip the response before caching it. Ungzipping is fast - so just ungzip for the 15% of the time the browser does not accept gzipping.
18.2 SimplePageCachingFilter
What if you just want to get started with the CachingFilter and dont want to think too hard? Just use SimplePageCachingFilter which has a calculateKey method already implemented. It uses httpRequest.getRequestURI()).append for the key. This works most of the time. It tends to get less effective when referrals and afliates are added to the query, which is the case for a lot of e-commerce sites. SimplePageCachingFilter is 10 lines of code. 81
18.3 PageFragmentCachingFilter
You notice that an entire page cannot be cached because the data on it vary in staleness. Say, an address which changes very infrequently, and the price and availability of inventory, which changes quite a lot. Or you have a portal, with lots of components and with different stalenesses. Or you use the replicated cache functionality in ehcache and you only want to rebuild the part of the page that got invalidated. Enter the PageFragmentCachingFilter. It does everyting that SimplePageCachingFilter does, except it never gzips, so the fragments can be combined.
18.4 SimplePageFragmentCachingFilter
What if you just want to get started with the PageFragmentCachingFilter and dont want to think too hard? Just use SimplePageFragmentCachingFilter which has a calculateKey method already implemented. It uses httpRequest.getRequestURI()).append(httpRequest.getQueryString() for the key. This works most of the time. It tends to get less effective when referrals and afliates are added to the query, which is the case for a lot of e-commerce sites. SimplePageFragmentCachingFilter is 10 lines of code.
82
Chapter 19
19.1 Acknowledgements
Much of the material here was drawn from Data Access Patterns, by Clifton Nock. Thanks to Will Pugh and ehcache contributor Surya Suravarapu for suggesting we take ehcache distributed. Finally, thanks to James Strachan for making helpful suggestions.
19.8.4 RMI RMI is the default RPC mechanism in Java. 19.8.5 JXTA
JXTA is a peer to peer technology that provides discovery and delivery, together with much else.
19.8.6 JGroups
JGroups provides many of the desired features for a peer to peer distributed system. The default mode for JGroups on a LAN is UDP, which is not desired. However JGroups does provide reliably transmission using TCP, similar to the approach taken in ehcache.
it itself is the default remoting mechanism in Java it is mature it allows tuning of TCP socket options Element keys and values for disk storage must already be Serializable, therefore directly transmittable over RMI without the need for conversion to a third format such as XML. it can be congured to pass through rewalls RMI had improvements added to it with each release of Java, which can then be taken advantage of. However the pluggable nature of ehcaches distribution mechanism allows for both of these approaches to be plugged in. These approaches may become a standard part of ehcache in a future release. A JGroups implementation is planned for ehcache-1.2.1.
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 updates via invalidation. These are discussed below:
87
88
Chapter 20
Distributed Caching
As of version 1.2, Ehcache can be used as a distributed cache. The distribution feature is built using plugins. Ehcache comes with some default distribution plugins which should be suitable for most applications. Other plugins can be developed. Developers should see the source code in the distribution package for the fullly documented API to see how to do that. Though not necessary to use distributed caching an insight into the design decisions used in ehcache may be helpful. See the Design of distributed ehcache page. The rest of this section documents the distribution plugins which are bundled with ehcache. The following concepts are central to cache distribution: How do you know about the other caches that are in your cluster? What form of communication will be used to distribute messages? What is replicated? Puts, Updates, Expiries? When is it replicated? Synchronous or asynchronous? To set up distributed caching you need to congure a PeerProvider, a CacheManagerPeerListener, which is done globally for a CacheManager. For each cache that will operate distributed, you then need to add a cacheEventListener to propagate messages.
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 conguration le.
90
properties="peerDiscovery=manual, rmiUrls=//server2:40001/sampleCache11|//server2:40001/sampleCache12"/>
Valid properties are: hostName (optional) - 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. The hostname is checked for reachability during CacheManager initialisation. If the hostName is unreachable, the CacheManager will refuse to start and an CacheException will be thrown indicating connection was refused. If unspecied, the hostname will use InetAddress.getLocalHost().getHostAddress(), which corresponds to the default host network interface. Warning: Explicitly setting this to localhost refers to the local loopback of 127.0.0.1, which is not network visible and will cause no replications to be received from remote hosts. You should only use this setting when multiple CacheManagers are on the same machine. port (mandatory) - the port the listener listens on. socketTimeoutMillis (optional) - the number of seconds client sockets will wait when sending messages to this listener until they give up. By default this is 2000ms. 91
<!-- 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, r </cache>
class - use net.sf.ehcache.distribution.RMICacheReplicatorFactory The factory recognises the following properties: replicatePuts=true |false - whether new elements placed in a cache are replicated to others. 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 asyncrhonous (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. 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 defaul <cache name="sampleCache4" maxElementsInMemory="10" eternal="true" overflowToDisk="false" memoryStoreEvictionPolicy="LFU"> <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/ </cache>
The default value in Java is 1, which propagates to the same subnet. Change the timeToLive property to restrict or expand propagation.
93
94
Chapter 21
21.1 Acknowledgements
Much of the material here was drawn from Concurrent Programming in Java by Doug Lea. Thanks also to Doug for answering several questions along the way.
Lets 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 rst 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.
Blocking Cache 97
It is blocking because all threads requesting the same key wait for the rst thread to complete. Once the rst thread has completed the other threads simply obtain the cache entry and return. The BlockingCache can scale up to very busy systems.
21.5.2 SelfPopulatingCache
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.
21.5.3 CachingFilter
You want to use the BlockingCache with web pages, 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 CachingFilter, a Servlet 2.3 compliant lter. Why not just do a JSP tag library, like OSCache? The answer is that you want the caching of your responses to be independent of the rendering technology. The lter chain is reexcuted every time a RequestDispatcher is involved. This is on every jsp:include and every Servlet. And you can programmatically add your own. If you have content generated by JSP, Velocity, XSLT, Servlet output or anything else, it can all be cached by CachingFilter. A separation of concerns. How do you determine what the key of a page is? The lter has an abstract calculateKey method, so it is up to you. You notice a problem and an opportunity. The problem is that the web pages you are caching are huge. That chews up either a lot of memory (MemoryStore) or a lot of disk space (DiskStore). Also you notive that these pages take their time going over the Internet. The opportunity is that you notice that all modern browsers support gzip encoding. A survey of logs reveals that 85% of the time the browser accepts gzipping. (The majority of the 15% that does not is IE behind a proxy). Ok, so gzip the response before caching it. Ungzipping is fast - so just ungzip for the 15% of the time the browser does not accept gzipping.
21.5.4 SimplePageCachingFilter
What if you just want to get started with the CachingFilter and dont want to think too hard? Just use SimplePageCachingFilter which has a calculateKey method already implemented. It uses httpRequest.getRequestURI()).append for the key. This works most of the time. It tends to get less effective when referrals and afliates are added to the query, which is the case for a lot of e-commerce sites. SimplePageCachingFilter is 10 lines of code.
21.5.5 PageFragmentCachingFilter
You notice that an entire page cannot be cached because the data on it vary in staleness. Say, an address which changes very infrequently, and the price and availability of inventory, which changes quite a lot. Or you have a portal, with lots of components and with different stalenesses. Or you use the replicated cache functionality in ehcache and you only want to rebuild the part of the page that got invalidated. Enter the PageFragmentCachingFilter. It does everyting that SimplePageCachingFilter does, except it never gzips, so the fragments can be combined. 98
21.5.6 SimplePageFragmentCachingFilter
What if you just want to get started with the PageFragmentCachingFilter and dont want to think too hard? Just use SimplePageFragmentCachingFilter which has a calculateKey method already implemented. It uses httpRequest.getRequestURI()).append(httpRequest.getQueryString() for the key. This works most of the time. It tends to get less effective when referrals and afliates are added to the query, which is the case for a lot of e-commerce sites. SimplePageFragmentCachingFilter is 10 lines of code.
21.5.7 AsynchronousCommandExecutor
What happens if your JMS server is down? The usual answer it to have two of them. Unfortunately, not all JMS servers do a good job of clustering. Plus it takes twice the hardware. Once a message makes it to a JMS server, they can usually be congured to store the message in a database. You are pretty safe after that if there is a crash. Enter AsynchronousCommandExecutor. It lets you create a command for future execution. The command is cached and is then immediately executed in another thread. Thus the asynchronous bit. If it fails, it retries on a set interval up to a set number of times. Thus it is fault-tolerant. Use this where you really dont want to lose messages or commands that execute against another system.
FilterNonReentrantException, AlreadyGzippedException and ResponseHeadersNotModiableException. These conditions are detected and an exception thrown rather than a blank page. Then the developer xes the coding error that produced it. The exception contain comments on how each issue happens, which are reproduced below: FilterNonReentrantException - Thrown when it is detected that a caching lters doFilter method is reentered by the same thread. Reentrant calls will block indenitely because the rst request has not yet unblocked the cache. Nasty. AlreadyGzippedException - 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. ResponseHeadersNotModiableException - 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 specication, setHeader silently fails. Two scenarios where this happens are: The response is committed. RequestDispatcher#include method caused the request. This issue is extremely subtle and nasty. There are tests that reproduce each of these issues. The CachingFilter and its subclasses have been in production for nearly two years with no more reports of trouble.
100
Chapter 22
22.1 Conguration
One CacheManagerEventListenerFactory and hence one CacheManagerEventListener can be specied per CacheManager instance. The factory is congured as below:
<cacheManagerEventListenerFactory class="" properties=""/>
The entry species a CacheManagerEventListenerFactory which will be used to create a CacheManagerPeerProvider, which is notied when Caches are added or removed from the CacheManager. The attributes of CacheManagerEventListenerFactory are: class - a fully qualied factory class name properties - comma separated properties having meaning only to the factory. 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 specied, or there is no cacheManagerEventListenerFactory element, no listener is created. There is no default. 101
/** * Called immediately after a cache has been added and activated. * <p/>
102
* 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.
103
104
Chapter 23
Cache Loaders
A CacheLoader is an interface which species 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 congured in ehcache.xml. CacheLoaders are invoked in the following Cache methods: getWithLoader (synchronous) getAllWithLoader (synchronous) load (asynchronous) loadAll (asynchronous) They are also invoked in similar (though slightly different 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 conguration le or programmatically. This becomes the default CacheLoader. Some of the methods invoking loaders enable an override CacheLoader to be passed in as a parameter.
105
/** * 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 programmatical * @author Greg Luck * @version $Id: cache_loaders.apt 536 2007-08-12 08:17:44Z gregluck $ */ 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.JCacheFac * 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 * 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); }
The factory creates a concrete implementation of the CacheLoader interface, which is reproduced below:
/** * Extends JCache CacheLoader with load methods that take an argument in addition to a key * @author Greg Luck * @version $Id: cache_loaders.apt 536 2007-08-12 08:17:44Z gregluck $ */ public interface CacheLoader extends net.sf.jsr107cache.CacheLoader {
/** * Load using both a key and an argument. * * JCache will call through to the load(key) method, rather than this method, where the argum * @param key the key to load the object for
106
* @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. * * 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(); }
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.
107
108
Chapter 24
24.1 Conguration
Cache event listeners are congured per cache. Each cache can have multiple listeners. Each listener is congured by adding a cacheManagerEventListenerFactory element as follows:
The entry species a CacheManagerEventListenerFactory which is used to create a CachePeerProvider, which then receives notications. The attributes of CacheManagerEventListenerFactory are: 109
class - a fully qualied factory class name * properties - an optional comma separated properties having meaning only to the factory. 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.
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/>
110
* Cache also has putQuiet and removeQuiet methods which do not notify listeners. * * @author Greg Luck * @version $Id: cache_event_listeners.apt 135 2006-06-26 06:55:03Z gregluck $ * @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/> * the cache emitting the notification * @param cache * @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 Elements fields, including value, so the * element is provided. Implementers should be careful not to modify the element. The * effect of any modifications is undefined. * the cache emitting the notification * @param cache @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 Elements fields, including value, so the * element is provided. Implementers should be careful not to modify the element. The * effect of any modifications is undefined. * the cache emitting the notification * @param cache * @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.
111
* <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. * the cache emitting the notification * @param cache * @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.
112
Chapter 25
113
* Extend to create a concrete factory * * @author <a href="mailto:[email protected]">Greg Luck</a> * @version $Id: cache_exception_handlers.apt 536 2007-08-12 08:17:44Z gregluck $ */ 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 CacheExceptionHandler * set at runtime (a strategy). * <p/> * If an exception handler is registered, the default behaviour of throwing the exception will not * method <code>onException</code> will be called. Of course, if the handler decides to throw the * propagate up through the call stack. If the handler does not, it wont. * <p/> * Some common Exceptions thrown, and which therefore should be considered when implementing this * <ul> * <li>{@link IllegalStateException} if the cache is not {@link net.sf.ehcache.Status#STATUS_ALIV * <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 synch * <li> * <li> * </ul> * * @author <a href="mailto:[email protected]">Greg Luck</a> * @version $Id: cache_exception_handlers.apt 536 2007-08-12 08:17:44Z gregluck $ */ public interface CacheExceptionHandler {
/** * Called if an Exception occurs in a Cache method. This method is not called * if an <code>Error</code> occurs. * the cache in which the Exception occurred * @param ehcache the key used in the operation, or null if the operation does not use a key * @param key * @param exception the exception caught */ void onException(Ehcache ehcache, Object key, Exception exception); }
See the chapter on Classloading for details on how classloading of these classes will be done.
115
116
Chapter 26
Cache Extensions
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.
<cache ...> <cacheExtensionFactory class="com.example.FileWatchingCacheRefresherExtensionFactory" properties="refreshIntervalMillis=18000, loaderTimeout=3000, flushPeriod=whatever, someOtherProperty=someValue ..."/> </cache>
/** * An abstract factory for creating <code>CacheExtension</code>s. Implementers should provide thei * concrete factory extending this factory. It can then be configured in ehcache.xml. * * @author <a href="mailto:[email protected]">Greg Luck</a> * @version $Id: cache_extensions.apt 535 2007-08-12 01:32:14Z gregluck $ */ public abstract class CacheExtensionFactory {
/** * @param cache the cache this extension should hold a reference to, and to whose lifecycle it * @param properties implementation specific properties configured as delimiter separated name */ 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 lifec * methods. * <p/> * CacheExtensions are created using the CacheExtensionFactory which has a <code>createCacheCache * method which takes as a parameter a Cache and properties. It can thus call back into any publi * 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 * CacheEventListener or even a CacheManagerEventListener, all from within a CacheExtension, creat * opportunities for customisation. * * @author <a href="mailto:[email protected]">Greg Luck</a> * @version $Id: cache_extensions.apt 535 2007-08-12 01:32:14Z gregluck $ */ public interface CacheExtension { /** * Notifies providers to initialise themselves. * <p/> * This method is called during the Caches initialise method after it has changed its statu * 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 dispos
118
/** * 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 th * 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;
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.
119
120
Chapter 27
Hibernate Caching
Note these instructions are for Hibernate 3.1. Go to Guide for Version 1.1 for older instructions on how to use Hibernate 2.1. 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 rst class cache for Hibernate. Since Hibernate 2.1, ehcache has been the default cache, for Hibernate. The net.sf.ehcache.hibernate package provides classes integrating ehcache with Hibernate. Hibernate is an application of ehcache. Ehcache is also widely used a general-purpose Java cache. To use ehcache with Hibernate do the following: Ensure ehcache is enabled in the Hibernate conguration. Add the cache element to the Hibernate mapping le, either manually, or via hibernatedoclet for each Domain Object you wish to cache. Add the cache element to the Hibernate mapping le, either manually, or via hibernatedoclet for each Domain Object collection you wish to cache. Add the cache element to the Hibernate mapping le, either manually, or via hibernatedoclet for each Hibernate query you wish to cache. Create a cache element in ehcache.xml Each of these steps is illustrated using a ctional Country Domain Object. For more about cache conguration 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.
To ensure ehcache is enabled, verify that the hibernate.cache.provider_class property is set to net.sf.ehcache.hibernate.EhCacheProvi in the Hibernate conguration le; either hibernate.cfg.xml or hibernate.properties. The format given is for hibernate.cfg.xml. 121
If you are using hibernate-3 or hibernate-3.1 you will need to use the ehcache provider to use multiple SessionFactories/CacheManagers in a single VM. That provider should be integrated into the Hibernate3.2 version.1
hibernate.cache.provider_class=net.sf.ehcache.hibernate.EhCacheProvider net.sf.ehcache.configurationResourceName=/name_of_configuration_resource
The meaning of the properties is as follows: hibernate.cache.provider_class - The fully qualied class name of the cache provider net.sf.ehcache.congurationResourceName - The name of a conguration 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 conguration to use. An example might be "ehcache-2.xml".
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider hibernate.cache.provider_configuration_file_resource_path=/name_of_configuration_resource
e.g.
27.2.1 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. This is an "asynchronous" concurrency strategy.
27.2.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. Congure your cache timeout accordingly! This is an "asynchronous" concurrency strategy. This policy is the fastest. It does not use synchronized methods whereas read-write and read-only both do.
27.2.3 read-only
Caches data that is never updated.
The @hibernate.cache usage tag should be set to one of read-write, nonstrict-read-write and read-only. 123
27.4.2 Hibernate
CacheConcurrencyStrategy read-write, nonstrict-read-write and read-only policies apply to Domain Objects.
27.4.3 Collections
Hibernate creates collection caches named after the fully qualied name of the Domain Object followed by "." followed by the collection eld 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 congured for the set. The ehcache.xml conguration looks like:
<cache name="com.somecompany.someproject.domain.Country" maxElementsInMemory="50"
124
eternal="false" timeToLiveSeconds="600" overflowToDisk="true" /> <cache name="com.somecompany.someproject.Country.advancedSearchFacilities" maxElementsInMemory="450" eternal="false" timeToLiveSeconds="600" overflowToDisk="true" />
27.4.5 Queries
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.4.6 StandardQueryCache
This cache is used if you use a query cache without setting a name. A typical ehcache.xml conguration is:
<cache name="org.hibernate.cache.StandardQueryCache" maxElementsInMemory="5" eternal="false" timeToLiveSeconds="120" overflowToDisk="true"/>
27.4.7 UpdateTimestampsCache
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 congured for expiry at all. A typical ehcache.xml conguration is:
<cache name="org.hibernate.cache.UpdateTimestampsCache" maxElementsInMemory="5000" eternal="true" overflowToDisk="true"/>
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"/>
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.
27.5.2 Object Id
Hibernate identies cached objects via an object id. This is normally the primary key of a database row.
27.5.3 Session.load
Session.load will always try to use the cache.
127
128
Chapter 28
Creating a JCache from an existing Cache in Ehcaches CacheManager This is the recommended way of using JCache. Caches can be congured in ehcache.xml and wrapped as JCaches with the getJCache method of CacheManager.
manager in the following sample is an net.sf.ehcache.CacheManager net.sf.jsr107cache.Cache cache = manager.getJCache("sampleCacheNoIdle");
129
Creating a JCache using the JCache CacheManager Warning: The JCache CacheManager is unworkable and will very likely be dropped in the nal JCache as a Class. It will likely be replaced with a CacheManager interface. The JCache CacheManager only works as a singleton. You obtain it with getInstance The CacheManager uses a CacheFactory to create Caches. The CacheFactory is specied using the Service Provider Interface mechanism introduced in JDK1.3. The factory is specied in the META-INF/services/net.sf.jsr107cache.CacheFactory resource le. This would normally be packaged in a jar. The default value for the ehcache implementation is
net.sf.ehcache.jcache.JCacheFactory
The conguration for a cache is assembled as a map of properties. Valid properties can be found in the JavaDoc for the JCacheFactory.createCache() method. See the following full example.
CacheManager singletonManager = CacheManager.getInstance(); CacheFactory cacheFactory = singletonManager.getCacheFactory(); assertNotNull(cacheFactory); Map config = new HashMap(); config.put("name", "test"); config.put("maxElementsInMemory", "10"); config.put("memoryStoreEvictionPolicy", "LFU"); config.put("overflowToDisk", "true"); config.put("eternal", "false"); config.put("timeToLiveSeconds", "5"); config.put("timeToIdleSeconds", "5"); config.put("diskPersistent", "false"); config.put("diskExpiryThreadIntervalSeconds", "120"); Cache cache = cacheFactory.createCache(config); singletonManager.registerCache("test", cache);
manager = CacheManager.getInstance(); Ehcache ehcache = new net.sf.ehcache.Cache("UseCache", 10, MemoryStoreEvictionPolicy.LFU, false, null, false, 10, 10, false, 60, null); manager.registerCache("test", new JCache(ehcache, null)); Cache cache = manager.getCache("test");
JCache also has some interesting asynchronous methods such as load and loadAll which can be used to preload the JCache.
The following is both a critique of JCache and notes on the Ehcache implementation. As a member of the JSR107 Expert Group these notes are also intended to be used to improve the specication.
28.3.1 net.sf.jsr107cache.CacheManager
CacheManager does not have the following features: shutdown the CacheManager - there is no way to free resources or persist. Implementations may utilise a shutdown hook, but that does not work for application server redeployments, where a shutdown listener must be used. List caches in the CacheManager. There is no way to iterate over, or get a list of caches. remove caches from the CacheManager - once its there it is there until JVM shutdown. This does not work well for dynamic creation, destruction and recreation of caches. CacheManager does not provide a standard way to congure caches. A Map can be populated with properties and passed to the factory, but there is no way a conguration le can be congured. This should be standardised so that declarative cache conguration, rather than programmatic, can be achieved.
28.3.2 net.sf.jsr107cache.CacheFactory
A property is specied in the resource services/net.sf.jsr107cache.CacheFactory for a CacheFactory. The factory then resolves the CacheManager which must be a singleton. A singleton CacheManager works in simple scenarios. But there are many where you want multiple CacheManagers in an application. Ehcache supports both singleton creation semantics and instances and denes the way both can coexist. The singleton CacheManager is a limitation of the specication. (Alternatives: Some form of annotation and injection scheme) Pending a nal JSR107 implementation, the ehcache conguration mechanism is used to create JCaches from ehcache.xml cong. 131
28.3.3 net.sf.jsr107cache.Cache
The spec is silent on whether a Cache can be used in the absence of a CacheManager. Requiring a CacheManager makes a central place where concerns affecting all caches can be managed, not just a way of looking them up. For example, conguration for persistence and distribution. Cache does not have a lifecycle. There is no startup and no shutdown. There is no way, other than a shutdown hook, to free resources or perform persistence operations. Once again this will not work for redeployment of applications in an app server. There is no mechanism for creating a new cache from a default conguration such as a public void registerCache(String cacheName) on CacheManager. This feature is considered indispensable by frameworks such as Hibernate. Cache does not have a getName() method. A cache has a name; that is how it is retrieved from the CacheManager. But it does not know its own name. This forces API users to keep track of the name themselves for reporting exceptions and log messages. Cache does not support setting a TTL override on a put. e.g. put(Object key, Object value, long timeToLive). This is a useful feature. The spec is silent on whether the cache accepts null keys and elements. Ehcache allows all implementations. i.e.
cache.put(null, null); assertNull(cache.get(null)); cache.put(null, "value"); assertEquals("value", cache.get(null)); cache.put("key", null); assertEquals(null, cache.get("key")); null is effectively a valid key. However because null id not an instance of Serializable null-
keyed entries will be limited to in-process memory. The load(Object key), loadAll(Collection keys) and getAll(Collection collection) methods specify in the javadoc that they should be asynchronous. Now, most load methods work off a database or some other relatively slow resource (otherwise there would be no need to have a cache in the rst place). To avoid running out of threads, these load requests need to be queued and use a nite number of threads. The ehcache implementation does that. However, due to the lack of lifecycle management, there is no immediate way to free resources such as thread pools. The load method ignores a request if the element is already loaded in for that key. get and getAll are inconsistent. getAll throws CacheException, but get does not. They both should.
/** * Returns a collection view of the values contained in this map. The * collection is backed by the map, so changes to the map are reflected in * the collection, and vice-versa. If the map is modified while an * iteration over the collection is in progress (except through the * iterators own <tt>remove</tt> operation), the results of the * iteration are undefined. The collection supports element removal, * which removes the corresponding mapping from the map, via the * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>, * <tt>removeAll</tt>, <tt>retainAll</tt> and <tt>clear</tt> operations.
132
* It does not support the add or <tt>addAll</tt> operations. * <p/> * * @return a collection view of the values contained in this map. */ public Collection values() {
It is not practical or desirable to support this contract. Ehcache has multiple maps for storage of elements so there is no single backing map. Allowing changes to propagate from a change in the collection maps would break the public interface of the cache and introduce subtle threading issues. The ehcache implementation returns a new collection which is not connected to internal structures in ehcache.
28.3.4 net.sf.jsr107cache.CacheEntry
getHits() returns int. It should return long because production cache systems have entries hit more than Integer.MAX_VALUE times. Once you get to Integer.MAX_VALUE the counter rolls over. See the following test:
public void testIntOverflow() { long value = Integer.MAX_VALUE; value += Integer.MAX_VALUE; value += 5; LOG.info("" + value); int valueAsInt = (int) value; LOG.info("" + valueAsInt); assertEquals(3, valueAsInt); }
getCost() requirs the CacheEntry to know where it is. If it is in a DiskStore then its cost of retrieval could be higher than if it is in heap memory. Ehcache elements do not have this concept, and it is not implemented. i.e. getCost always returns 0. Also, if it is in the DiskStore, when you retrieve it is in then in the MemoryStore and its retrieval cost is a lot lower. I do not see the point of this method. getLastUpdateTime() is the time the last "update was made". JCACHE does not support updates, only puts
28.3.5 net.sf.jsr107cache.CacheStatistics
getObjectCount() is a strange name. How about getSize()? If a cache entry is an object graph each entry will have more than one "object" in it. But the cache size is what is really meant, so why not call it that? Once again getCacheHits and getCacheMisses should be longs.
public interface CacheStatistics { public static final int STATISTICS_ACCURACY_NONE = 0; public static final int STATISTICS_ACCURACY_BEST_EFFORT = 1; public static final int STATISTICS_ACCURACY_GUARANTEED = 2; public int getStatisticsAccuracy();
133
public int getObjectCount(); public int getCacheHits(); public int getCacheMisses(); public void clearStatistics();
There is a getStatisticsAccuracy() method but not a corresponding setStatisticsAccuracy method on Cache, so that you can alter the accuracy of the Statistics returned. Ehcache supports this behaviour. There is no method to estimate memory use of a cache. Ehcache serializes each Element to a byte[] one at a time and adds the serialized sizes up. Not perfect but better than nothing and works on older JDKs. CacheStatistics is obtained using cache.getCacheStatistics() It then has getters for values. In this way it feels like a value object. The ehcache implementation is Serializable so that it can act as a DTO. However it also has a clearStatistics() method. This method clear counters on the Cache. Clearly CacheStatistics must hold a reference to Cache to enable this to happen. But what if you are really using it as a value object and have serialized it? The ehcache implementation marks the Cache reference as transient. If clearStatistics() is called when the cache reference is no longer there, an IllegalStateException is thrown. A much better solution would be to move clearStatistics() to Cache.
28.3.6 net.sf.jsr107cache.CacheListener
/** * Interface describing various events that can happen as elements are added to * or removed from a cache */ public interface CacheListener { /** Triggered when a cache mapping is created due to the cache loader being consulted */ public void onLoad(Object key); /** Triggered when a cache mapping is created due to calling Cache.put() */ public void onPut(Object key); /** Triggered when a cache mapping is removed due to eviction */ public void onEvict(Object key); /** Triggered when a cache mapping is removed due to calling Cache.remove() */ public void onRemove(Object key); public void onClear(); }
Listeners often need not just the key, but the cache Entry itself. This listener interface is extremely limiting. There is no onUpdate notication method. These are mapped to JCACHEs onPut notication. There is no onExpired notication method. These are mapped to JCACHEs onEvict notication. 134
28.3.7 net.sf.jsr107cache.CacheLoader
JCache can store null values against a key. In this case, on JCache#get or getAll should an implementation attempt to load these values again? They might have been null in the system the CacheLoader loads from, but now arent. The ehcache implementation will still return nulls, which is probably the correct behaviour. This point should be claried.
135
136
Chapter 29
29.1.1 If I restart/reload a web application in Tomcat that has a CacheManager that is part of a cluster, the CacheManager is unable to rejoin the cluster. If I set logging for net.sf.ehcache.distribution to FINE I see the following exception: "FINE: Unable to lookup remote cache peer for .... Removing from peer list. Cause was: error unmarshalling return; nested exception is: java.io.EOFException.
The Tomcat and RMI classloaders do not get along that well. Move ehcache.jar to $TOMCAT_HOME/common/lib. This xes the problem. This issue happens with anything that uses RMI, not just ehcache.
29.1.2 In development, there appear to be classloader memory leak as I continually redeploy my web application.
There are lots of causes of memory leaks on redeploy. Moving ehcache and backport-util-concurrent out of the WAR and into $TOMCAT/common/lib xes this leak.
29.1.3 I get net.sf.ehcache.CacheException: Problem starting listener for RMICachePeer ... java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: java.net.MalformedURLException: no protocol: Files/Apache. What is going on?
This issue occurs to any RMI listener started on Tomcat whenever Tomcat has spaces in its installation path. 137
It is is a JDK bug which can be worked around in Tomcat. See http://archives.java.sun.com/cgi-bin/wa?A2=ind0205&L=rmi-users&P=797 and http://www.ontotext.com/kim/doc/sysdoc/faq-howto-bugs/known-bugs.html. The workaround is to remove the spaces in your tomcat installation path.
29.1.4 Multiple Host Entries in Tomcats server.xml stops replication from occurring
The presence of multiple Host entries in Tomcats server.xml prevents replication from occuring. The issue is with adding multiple hosts on a single Tomcat connector. If one of the hosts is localhost and another starts with v, then the caching between machines when hitting localhost stops working correctly. The workaround is to use a single Host entry or to make sure they dont start with "v". Why this issue occurs is presently unknown, but is Tomcat specic.
138
Chapter 30
This deploys to http://ehcache.sourceforge.net/repository/ which is synced with the Maven central repository.
140
Chapter 31
31.2 Can you use more than one instance of ehcache in a single VM?
As of ehcache-1.2, yes. Create your CacheManager using new CacheManager(...) and keep hold of the reference. The singleton approach accessible with the getInstance(...) method is still available too. Remember that ehcache can supports hundreds of caches within one CacheManager. You would use separate CacheManagers where you want quite different congurations. The Hibernate EhCacheProvider has also been updated to support this behaviour.
31.3 Can you use ehcache with Hibernate and outside of Hibernate at the same time?
Yes. You use 1 instance of ehcache and 1 ehcache.xml. You congure your caches with Hibernate names for use by Hibernate. You can have other caches which you interact with directly outside of Hibernate. That is how I use ehcache in the original project it was developed in. For Hibernate we have about 80 Domain Object caches, 10 StandardQueryCaches, 15 Domain Object Collection caches. We have around 5 general caches we interact with directly using BlockingCacheManager. We have 15 general caches we interact with directly using SelfPopulatingCacheManager. You can use one of those or you can just use CacheManager directly. I have updated the documentation extensively over the last few days. Check it out and let me know if you have any questions. See the tests for example code on using the caches directly. Look at CacheManagerTest, CacheTest and SelfPopulatingCacheTest. 141
31.4 What happens when maxElementsInMemory is reached? Are the oldest items are expired when new ones come in?
When the maximum number of elements in memory is reached, the least recently used ("LRU") element is removed. Used in this case means inserted with a put or accessed with a get. If the overowToDisk cache attribute is false, the LRU Element is discarded. If true, it is transferred asynchronously to the DiskStore.
31.5 Is it thread safe to modify Element values after retrieval from a Cache?
Remember that a value in a cache element is globally accessible from multiple threads. It is inherently not thread safe to modify the value. It is safer to retrieve a value, delete the cache element and then reinsert the value. The UpdatingCacheEntryFactory does work by modifying the contents of values in place in the cache. This is outside of the core of ehcache and is targeted at high performance CacheEntryFactories for SelfPopulatingCaches.
31.7 Why is there an expiry thread for the DiskStore but not for the MemoryStore?
Because the memory store has a xed maximum number of elements, it will have a maximum memory use equal to the number of elements * the average size. When an element is added beyond the maximum size, the LRU element gets pushed into the DiskStore. While we could have an expiry thread to expire elements periodically, it is far more efcient to only check when we need to. The tradeoff is higher average memory use. The DiskStores size is unbounded. The expiry thread keeps the disk store clean. There is hopefully less contention for the DiskStores locks because commonly used values are in the MemoryStore. We mount our DiskStore on Linux using RAMFS so it is using OS memory. While we have more of this than the 2GB 32 bit process size limit it is still an expensive resource. The DiskStore thread keeps it under control. If you are concerned about cpu utilisation and locking in the DiskStore, you can set the diskExpiryThreadIntervalSeconds to a high number - say 1 day. Or you can effectively turn it off by setting the diskExpiryThreadIntervalSeconds to a very large value.
31.11 Where is the source code? The source code is distributed in the root directory of the download.
It is called ehcache-x.x.zip. It is also available from SourceForge online or through SVN.
31.14 Do you need to call CacheManager.getInstance().shutdown() when you nish with ehcache?
Yes, it is recommended. If the JVM keeps running after you stop using ehcache, you should call CacheManager.getInstance().shutdown() so that the threads are stopped and cache memory released back to the JVM. Calling shutdown also insures that your persistent disk stores get written to disk in a consistent state and will be usable the next time they are used. If the CacheManager does not get shutdown it should not be a problem. There is a shutdown hook which calls the shutdown on JVM exit. This is explained in the documentation here.
31.16 I have created a new cache and its status is STATUS_UNINITIALISED. How do I initialise it?
You need to add a newly created cache to a CacheManager before it gets intialised. Use code like the following:
CacheManager manager = CacheManager.create(); Cache myCache = new Cache("testDiskOnly", 0, true, false, 5, 2); manager.addCache(myCache);
31.20 I get net.sf.ehcache.distribution.RemoteCacheException: Error doing put to remote peerremote peer. Message was: Error unmarshaling return header; nested exception is: java.net.SocketTimeoutExcep Read timed out. What does this mean.
It typically means you need to increase your socketTimeoutMillis. This is the amount of time a sender should wait for the call to the remote peer to complete. How long it takes depends on the network and the size of the Elements being replicated. The conguration that controls this is the socketTimeoutMillis setting in cacheManagerPeerListenerFactory. 120000 seems to work well for most scenarios.
<cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
144
31.21 Should I use this directive when doing distributed caching? cacheManagerEventListenerFactory class="" properties=""/
No. It is unrelated. It is for listening to changes in your local CacheManager.
<cacheManagerPeerListenerFactory class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/>
<cache name="sampleDistributedCache1" maxElementsInMemory="10" eternal="false" timeToIdleSeconds="100" timeToLiveSeconds="100" overflowToDisk="false"> <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/ </cache>
31.24 Why cant I run multiple applications using ehcache on one machine?
Because of an RMI bug, in JDKs before JDK1.5 such as JDK1.4.2, ehcache is limited to one CacheManager operating in distributed mode per virtual machine. (The bug limits the number of RMI registries to one per virtual machine). Because this is the expected deployment conguration, however, there should be no practical effect. The tell tail error is java.rmi.server.ExportException: internal error:
ObjID already in use
On JDK1.5 and higher it is possible to have multiple CacheManagers per VM each participating in the same or different clusters. Indeed the replication tests do this with 5 CacheManagers on the same VM all run from JUnit.
31.25 How many threads does ehcache use, and how much memory does that consume?
The amount of memory consumed per thread is determined by the Stack Size. This is set using -Xss. The amount varies by OS. It is 512KB for Linux. I tend to override the default and set it to 100kb. The threads are created per cache as follows: DiskStore expiry thread - if DiskStore is used DiskStore spool thread - if DiskStore is used Replication thread - if asynchronous replication is congured. If you are not doing any of the above, no extra threads are created
31.26 I am using Tomcat 5, 5.5 or 6 and I am having a problem. What can I do?
Tomcat is such a common deployment option for applications using ehcache that there is a chapter on known issues and recommended practices. See the Using Ehcache with Tomcat chapter. (http://ehcache.sourceforge.net/documentati
146
Chapter 32
The logo is similarly symmetrical, and is evocative of the diagram symbol for a doubly-linked list. The JDK1.4 LinkedHashMap, and Apaches LRUMap are a HashMap with a doubly-linked list running through all of its entries. These structures lie at the heart of ehcache.
147
Index
A Central Maven Repository . . . . . . . . . . . . . . . . . . . 140 About the ehcache name and logo . . . . . . . . . 12, 147 Code Samples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Adam Murdoch . . . . . . . . . . . . . . . . . . . . . . . . . 12, 147 Commons Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Adding and Removing Caches Programmatically56 Conguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .109 Amdahls Law . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Conservative Commit policy . . . . . . . . . . . . . . . . . . 30 Apache 2.0 license . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Copy Or Invalidate Replication . . . . . . . . . . . . . . . . 27 AsynchronousCommandExecutor . . . . . . . . . . . . . . 99 CPU bound Applications . . . . . . . . . . . . . . . . . . . . . 14 Automated Load, Limit and Performance System Tests Creating a new cache from defaults . . . . . . . . . . . . 59 Creating a new cache with custom parameters . . . 59 29 Automatic Peer Discovery . . . . . . . . . . . . . . . . . . . . 90 D Deadlock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 B Blocking Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 DEBUG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .63 Blocking Cache to avoid duplicate processing for Disk Persistence on demand . . . . . . . . . . . . . . . . . . . 58 concurrent operations . . . . . . . . . . . . . . . 28 DiskStore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 BlockingCache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 DiskStore Eviction Algorithms . . . . . . . . . . . . . . . . 54 Bootstrapping from Peers . . . . . . . . . . . . . . . . . . . . . 28 Distributed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Browse the JUnit Tests . . . . . . . . . . . . . . . . . . . . . . . 60 Distributed Caching . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Building an ehcache distribution from source . . 139 Distributed Failure . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Building from Source . . . . . . . . . . . . . . . . . . . . . . . 139 E Building the Site . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 Ehcache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 ehcache constructs . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 C Cache Conguration . . . . . . . . . . . . . . . . . . . . . . . . . 37 ehcache.xsd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 ehcache-1.x-remote-debugger.jar . . . . . . . . . . . . . . 64 Cache Decorators . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Element . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Cache Event Listeners . . . . . . . . . . . . . . . . . . . . . . . 109 ERROR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Cache event listeners . . . . . . . . . . . . . . . . . . . . . . . . . 26 Eviction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 Cache Eviction Algorithms . . . . . . . . . . . . . . . . . . . 53 Expiry Strategy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 Cache Exception Handlers . . . . . . . . . . . . . . . . . . . 113 Extensible . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Cache Exception Handlers may be plugged in . . . 26 Cache Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 F Cache Extensions may be plugged in . . . . . . . . . . . 26 Fast . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 Cache Loaders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Cache Loaders may be plugged in . . . . . . . . . . . . . 26 FIFO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Cache Usage Patterns . . . . . . . . . . . . . . . . . . . . . . . . . 36 First In First Out . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Cacheable Commands . . . . . . . . . . . . . . . . . . . . . . . . 28 Flush to disk on demand . . . . . . . . . . . . . . . . . . . . . . 26 CacheExceptionHandlerFactory . . . . . . . . . . . . . . 113 Full implementation of JSR107 JCACHE API . . 25 CacheExtensionFactory . . . . . . . . . . . . . . . . . . . . . .117 Full public information on the history of every bug CacheLoaderFactory . . . . . . . . . . . . . . . . . . . . . . . . 106 30 CacheManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Fully documented . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 CacheManager Event Listeners . . . . . . . . . . . . . . . 101 CacheManager listeners . . . . . . . . . . . . . . . . . . . . . . 26 G CacheManagerEventListener . . . . . . . . . . . . . . . . . 102 Garbage Collection . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 CacheManagerEventListenerFactory . . . . . . . . . . 102 General Purpose Caching . . . . . . . . . . . . . . . . . . . . . 19 CachingFilter . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81, 98 generic extensions to a Cache . . . . . . . . . . . . . . . . 117 148
H Hibernate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Hibernate 2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Hibernate 3.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Hibernate Caching . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Hibernate Doclet . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 Hibernate Mapping Files . . . . . . . . . . . . . . . . . . . . 122 High Quality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 High Test Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Memory Store . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 MemoryStore Eviction Algorithms. . . . . . . . . . . . .53 Minimal dependencies . . . . . . . . . . . . . . . . . . . . . . . . 24 Missed Signals. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .96 Mixed Singleton and Instance Mode . . . . . . . . . . . 33 Multiple CacheManagers per virtual machine . . . 24 N Nested monitor lockouts . . . . . . . . . . . . . . . . . . . . . . 96
O I I/O bound Applications . . . . . . . . . . . . . . . . . . . . . . . 14 Obtaining a reference to a Cache . . . . . . . . . . . . . . 57 Obtaining Implementing a CacheEventListenerFactory and CacheEventLis- Cache Sizes . . . . . . . . . . . . . . . . . . . . . . . . 58 tener . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .110 Obtaining Statistics of Cache Hits and Misses . . . 59 Instance Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Open Source Licensing . . . . . . . . . . . . . . . . . . . . . . . 30 P PageFragmentCachingFilter . . . . . . . . . . . . . . . 82, 98 Peer Discovery . . . . . . . . . . . . . . . . . . . . . . . . . . . 27, 89 Peer Discovery, Replicators and Listeners may be plugged in . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Performance Considerations. . . . . . . . . . . . . . . . . . .73 performance tests fail . . . . . . . . . . . . . . . . . . . . . . . .139 Performing CRUD operations . . . . . . . . . . . . . . . . . 57 Persistence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Persistent disk store which stores data between VM restarts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Plugin class loading . . . . . . . . . . . . . . . . . . . . . . . . . . 71 Production tested . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Programmatic setting of the Hibernate Cache Provider 122 Provides LRU, LFU and FIFO cache eviction poliK cies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Key Ehcache Concepts . . . . . . . . . . . . . . . . . . . . . . . 31 Provides Memory and Disk stores . . . . . . . . . . . . . 25 Provides Memory and Disk stores for scalabilty into L gigabytes . . . . . . . . . . . . . . . . . . . . . . . . . . .24 Least Recently Used . . . . . . . . . . . . . . . . . . . . . . 50, 53 Less Frequently Used . . . . . . . . . . . . . . . . . . . . . 50, 54 R LFU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50, 54 Registering CacheStatistics in an MBeanServer . 60 Listeners may be plugged in . . . . . . . . . . . . . . . . . . . 25 Reliable Delivery . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Livelock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Remote Network debugging and monitoring for DisLiveness Failures . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 tributed Caches . . . . . . . . . . . . . . . . . . . . . 64 Loading of ehcache.xml resources . . . . . . . . . . . . . 72 replaceCacheWithDecoratedCache . . . . . . . . . . . . . 75 Locality of Reference. . . . . . . . . . . . . . . . . . . . . . . . .13 Resource Exhaustion . . . . . . . . . . . . . . . . . . . . . . . . . 96 log4j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Responsiveness to serious bugs . . . . . . . . . . . . . . . . 30 LRU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50, 53 Running Tests for Ehcache . . . . . . . . . . . . . . . . . . . 139 J Java EE and Applied Caching . . . . . . . . . . . . . . . . . 28 Java EE Gzipping Servlet Filter . . . . . . . . . . . . . . . .28 Java EE Servlet Caching . . . . . . . . . . . . . . . . . . . . . . 81 Java Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 JConsole Example . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 JDK1.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 JDK1.4 logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 JMX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 JMX Enabled . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 JMX Management and Monitoring . . . . . . . . . . . . . 67 JMX Remoting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 JMX Tutorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 JSR107 (JCACHE) Support . . . . . . . . . . . . . . . . . . 129 JSR107 Implementation . . . . . . . . . . . . . . . . . . . . . 129 M Management Service . . . . . . . . . . . . . . . . . . . . . . . . . 68 Manual Peer Discovery . . . . . . . . . . . . . . . . . . . . . . . 90 Maven . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 maxElementsInMemory . . . . . . . . . . . . . . . . . . . . . . 53 maxElementsOnDisk . . . . . . . . . . . . . . . . . . . . . . . . . 53 MBeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 MBeanServerConnection . . . . . . . . . . . . . . . . . . . . . 68 S Safety Failures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Scalable to hundreds of caches . . . . . . . . . . . . . . . . 24 SelfPopulating Cache for pull through caching of expensive operations . . . . . . . . . . . . . . . . 28 SelfPopulatingCache . . . . . . . . . . . . . . . . . . . . . . 77, 98 Setting ehcache as the cache provider . . . . . . . . . 121 Shutdown the CacheManager . . . . . . . . . . . . . . . . . .57
149
Shutting Down Ehcache . . . . . . . . . . . . . . . . . . . . . . 79 Simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 SimpleLog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 SimplePageCachingFilter . . . . . . . . . . . . . . . . . . 81, 98 SimplePageFragmentCachingFilter . . . . . . . . . 82, 99 Singleton Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Singleton versus Instance . . . . . . . . . . . . . . . . . . . . . 56 Small foot print . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Sourceforge Release. . . . . . . . . . . . . . . . . . . . . . . . .140 Specic Concurrency Testing . . . . . . . . . . . . . . . . . .29 Spooling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 Stampede . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Starvation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Support cache-wide or Element-based expiry policies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Supported MemoryStore Eviction Algorithms . . . 53 Supports Object or Serializable caching . . . . . . . . 24 Synchronous Or Asynchronous Replication . . . . . 27 T The Long Tail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Transparent Replication . . . . . . . . . . . . . . . . . . . . . . .27 Trusted by Popular Frameworks . . . . . . . . . . . . . . . 30 Tuned for high concurrent load on large multi-cpu servers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 U Using Caches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Using JCACHE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 Using the CacheManager . . . . . . . . . . . . . . . . . . . . . 55 Using the ehcache provider from the Hibernate project 122 W WARNING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Ways of loading Cache Conguration . . . . . . . . . . 56 Works with Hibernate . . . . . . . . . . . . . . . . . . . . . . . . 29
150