Probably it’s not really worth mentioning, but somehow I just once again got aware how incredibly important, in the age of open-source software and (talking about Java) a certain set of standard technologies, it is to, before getting any coding work done, it is to check what’s already around, to see whether there is a good solution that doesn’t require reinventing the wheel. In a current situation, I was thinking about how to make a Java based backend application (used by a web frontend system) faster by limiting access to our SQL database as well as the server filesystem to a bare minimum. One doesn’t need to think twice to come up with the omnipresent idea of caching…
… and, second idea probably is rather straightforward: Throw some Map implementation somewhere (possibly being a Singleton class) to house objects of a certain class identified by some good key. Make your data access objects look into that Map before querying an object from the SQL database and make them deliver the “cached” instance instead if there is one. Possibly add a few other information to the caching map in some way, like caching duration / expiry time… Possibly, this even will work out initially, given time and experience to merge this structure with your code. But sooner or later, you’re likely to stumble across a bunch of things maybe you initially forgot about:
- How to correctly handle expiration of cached objects as well as “refreshing” of those that have been modified and need to be persisted and then possibly cached again?
- How to easily make this concept work for a whole bunch of different objects (come on, you don’t just use one DAO and one sort of entities, do you?) without having to rebuild all of the data access code in question?
- How to completely test the whole mess to be sure your caching doesn’t do undesirable things to your data?
- How to possibly get this extended and/or changed once you see that, in example, one or two of your entities are accessed in a way that makes caching not really useful?
Maybe there’s a whole lot of other questions like this. If you’re the system administrator kind of guy (like I am, in some respects), you might want to go right the way you’d usually go using your everyday best friends in order to quickly hack up a heap of code to do the job. However, at least after getting deeper into Java, more than once I figured out that quite an amount of work can be saved looking closer at what is around before getting some work done. In case of Java and said caching issue, I came across a bunch of useful things:
- There is JSR 107 describing a mechanism fitting my very caching needs. This is good, given that the JSRs usually are agreed-upon by a more or less huge developer community so one can be sure to find good implementations as well as, if needed, help on these things.
- Likewise, there is ehcache which implements JSR-107 and provides a stable, usable general-purpose Java object cache which, oh joy ( 🙂 ), might be easily included into the environment our applications is built upon (tomcat, spring).
- And, finally, making use of Spring and AOP allows for adding caching functionality to the data access layer of the application in question just by configuration, without having to actually touch the DAO code (which, in our application sometimes is really messed-up and hard to debug, given we’re building atop a legacy database system).
Bottom line: Maybe I would have been out faster just implementing a set of self-made caching classes making use of Maps and adding them to my DAO layer. But this way surely I would have ended up with a lot more maintaineance work (getting the DAOs to do what they’re supposed to, again), and I would have left our system with another “proprietary”, possibly undocumented solution. The idea of making use of (standardized) components that are available, tested, stable and well-known however made me end up with a solution which, once put in place, just does its job without having to think twice about it. I’m not sure how soon the amount of time saved in maintaineance and testing might exceed the higher amount of time needed to get all this work together nicely… but I think that not to reinvent the wheel has been a good decision about that, so far. It wouldn’t have been a “really good” wheel in the end, after all… 🙂