Recently I’ve been dealing with caching at work, and wrote a web service of my own that needed some caching too. I took this opportunity to look into JCache (JSR 107). There are some good caches out there that implement this standard, but because I wanted something light weight for my web service and I really wanted to get familiar with the standard I decided to go ahead and write a trivial implementation myself. What follows are some of my observations about the standard from both an implementer’s and a user’s perspectives.
As a User
The API is very straight forward, especially for the general use cases. It is somewhere between a Map and a ConcurrentHashMap, with some of the more powerful conditional methods like getAnd*, compute and replace variations. The cache set up is sane too, although some of the more elaborate features can get a little involved to get going.
- Allows for swapping various implementations at will.
- Sane API with good feature set. Easy to use.
- More involved setups start requiring a fair bit of boilerplate code, rife with Factory and Listener subclassing. Hopefully the next round of the spec will include some JDK 8+ functional goodies and clean that up.
- Some of the bulk operations APIs don’t seem particularly optimized. For example there was no intuitive way to prime the cache except by passing in a specific key set.
As an Implementer
Implementing a minimal set, i.e. useful but not compliant, was straight forward. Once I moved on the the more peripheral features things got a little less pleasant. It feels like the core API was given a lot more thought then some of the lesser features.
- Basic API is clean and logical. Documentation covers semantics pretty well. There’s a reference implementation to double check things on.
- Get a useful product by implementing a clear subset.
- Added it’s own Key/Value interface rather then us Map.Entry. Exact signature match, but distinct. The API’s include uses of the standard Java collections but but the cache requires a unique Entry classes. Forces unnecessary conversions.
- Really suffers from it’s timing prior to JDK 1.8. Every consumer function has a distinct non-functional signature.
- Has a weak “unwrap” pattern to cast types that really doesn’t help things much.
I’ll definitely gravitate to this API for caching. It’s clean, powerful enough, and has a good selection of implementations. I’m hoping that as the spec evolves and incorporates JDK 8+ features most of the rough edges smooth away.
If you are curious about my partial implementation it can be found here on github.