Since version 2.x, Apache Commons JCS implements JCache specification (and a few more providing some basic utilities in its extras module and a basic integration with apache OpenJPA).
Next section is about main differences between JCache design and original JCS one. These are still globally valid and are kept to let you get a bit more food for thoughts on Caching and JCS.
The JCS is an attempt to build a system close to JCACHE , JSR-107, a description of the caching system used in Oracle9i. JCS grew out of my work over the past two years to build an enterprise level caching system. Though it is replete with good ideas, there are some aspects of the JCACHE architecture that could lead to inefficiency (ex, the lateral distribution and net searches) and a few programming preferences that I found cumbersome (ex, the use of exceptions to report the common place). Subsequently there are a few differences between the two systems. In some cases I have moved my original system closer to the JCACHE model where it presented a better idea. Briefly:
My original cache was regionally defined. Each entry required a very minimal wrapper. The osc4j specification is an element driven model where each element is fully configurable. This could lead to a slight performance penalty, but it is a richer model, where elements can inherit or have their own attributes. So, I converted the entire system into element centered framework.
The oracle model is a laterally distributed framework with no centralized control. The JCS model has the option for lateral broadcast (which will need to be made more efficient) and a remote store that coordinates consistency. In the JCS Local caches send data to the remote store which then notifies other local caches of changes to "regions" (caches) that are registered. In JCACHE's lateral model an update is never broadcast from the remote, rather updates come via the lateral caches. If you broadcast changes to all servers then every server must be ready for every user. The usage patterns of a user on one box can affect the whole. Also, the lateral model can make it difficult to synchronize combinations of updates and invalidations.
With a remote store the local caches are primed to take on similar patterns by talking to the remote store, but aren't flooded with the elements from another machine. This significantly cuts down on traffic. This way each local cache is a relatively separate realm with remotely configurable regions that stay in synch without overriding the user habits of any machine. It also allows for an efficient mechanism of retrieval, where searching for an element involves, at maximum, only as many steps as there are remote servers in the cluster. In the lateral model a failed net search could take an extremely long time to complete, making it necessary for the programmer to decide how long of a wait is acceptable.
Though this is by and large a poor model, the JCS will include the ability to perform full lateral searches. A more important feature is remote failover and remote server clustering. With clustering any concerns about the remote server being a single point of failure vanish and the remote server model is significantly more robust.
The difference between put and replace is not present in the JCS by default. The overhead associated with this distinction is tremendous. However, there will be an alternate "safe-put" method to deal with special caches.
I started to support ObjectNotFoundExceptions for failed gets but the overhead and cumbersome coding needed to surround a simple get method is ridiculous. Instead the JCS returns null.
I'm not supporting cache loaders at this time. They seem unnecessary, but may be useful in a smart portal.
The JCS provides feature rich grouping mechanism, where groups of elements can be invalidated and whose attributes can be listed. The grouping feature is much like the session API. In addition, the JCS provides a mechanism for hierarchical removal without the overhead of keeping track of all the elements of a group across machines. Element keys with ":" separators (a value that will be fully configurable) can be arranged in a hierarchy. A remove command ending in a ":" will issue a removal of all child elements. I can associate search and menu drop down lists for a particular company in a multi-company system by starting each key in disparate caches with the company id followed by ":" and then the normal key. Invalidating this data when a change is made to data affecting something falling under that company can be removed by simply calling cacheAccess.remove(comp_id + ":").