Data caches are good. Even distributed, shared, clustered data caches are good. There are many applications where this is the right thing to use.
Comparing them to Javaspaces is kind of nagging at me. In some cases one product can serve both purposes. E.g. in Gigaspaces, the developer can choose the Javaspace API or the Map/Cache API. They can also do funky update-in-place things within a space kind of too, but that is explicitly not in the Javaspaces API per se.
In any case I think it is imperative that a developer chooses what kind of mechanism they need for specific situations. And I think there are critical differences between the Javaspace mechanism and a data cache mechanism.
In particular, certain data caches run *in* the address space of the client JVMs, while a Javaspace is *never* in the address space of the client JVMs. (There are caches that run outside the address space, e.g. memcache, and that's another angle on the topic.) When these caches use the
java.util.Map API there are potentially funky goblins at play. A regular java Map has certain expectations.
Consider an object V1 with a direct object reference to object O1. Now consider another object K1. Put V1 in a shared, clustered cache using K1 as the key. Update object O1 in that JVM. In another JVM in the cluster (JVM'), do
cache.get(K1') to get a copy of V1' referencing a copy of O1'.
In this second JVM', update that O1'. Then from there do
cache.put(K1', V1'). Note: a cache is *not* a transparent transactional memory OODB like Gemstone/S or Gemstone/J. Not that you'd want one of those anymore, but they do go to pains to maintain referential integrity, which is the cliff this example is heading off of. So the
put in JVM' will soon update the first JVM so that the key K1' leads to the value V1' with a reference to the object O1'.
Meanwhile in the first JVM there is still, outside the cache, the objects K1, V1, and O1, with V1 referencing O1. When this JVM does
cache.get(K1) it gets back V1' with a reference to O1'.
Question: In the first JVM what are the identities of the objects K1, K1', V1, V1', O1, and O1'?
Answer: I believe the answer is dependent on the cache implementation. I am not sure what the JCache spec says. Either there is leeway or not all caches do the same thing, and none of these things may be what the developer expects based on experience using the out of the box
java.util.Map classes in single or concurrent threads.
In JBoss Cache the developer has the choice of a "tree cache" or a "pojo cache" (maybe others). The behavior will be different based on this choice. A pojo map will patch up object references *within* the stream used to cluster the distributed caches. The tree cache does not. And I think this behavior can vary based on the use of their AOP mechanism.
Even the pojo cache though does not patch up references as far as I can tell, ever, among cached objects and their former references in a JVM outside the cache per se. I.e. the deserializer does not do a sweep of the entire JVM address space to fix identity problems.
This is not necessarily a bad thing when the cache is used as a read-mostly, shared data cache backing some external data with a well-controlled update convention.
A Javaspace does not have this problem because of a simplifying specification -- Javaspaces do not deal with object identity in JVMs. You always get a new object. If you want to deal with identity then code it yourself in the Entry objects. But really don't do that very much!
That is different, and maybe not what you'd want at first. But that may indicate your not using the best mechanism for your problem or you're not thinking about the mechanism the best way yet. This is one of those "architectural constraints" that seem to get in your way, but actually can simplify the solution to a problem for certain classes of problems. E.g. when the problem is "coordination" of processing rather than "clustering" of read-mostly data.