1) Client puts a value object to NamedCache Value is decorated with flags that serve as hints to CacheStore when executing database updates
2) Cache store does the store operation
3) Now I would like to modify the object
4) Put modified object to backing map
What approach would you suggest to achieve that? Do you think that providing a custom BinaryEntryStore is a way to go? In JavaDoc I have learned that:
If the store operation changes the entry's value, a best effort will be made to place the changed value back into the corresponding backing map (for asynchronous store operations a concurrent backing map modification can make it impossible)+
This could serve my purpose until I decide to enable asynchronous write.
What is the problem you are trying to solve by decorating the object? Is it to suppress persistence in certain cases? Or to control how its done? Something else?
This is a tricky area, especially if you switch to write-behind, when as you suggest, it is not possible to update the backing map from the CacheStore. Also, updates may be coalesced, losing intermediate values.
Client application sets flags on rows of a table it has updated. Basically the data we store in the cache are tables, where some of them are massive in size. This way the algorithm that persists the data knows which rows of the table require SQL update. After persisting the value I need to reset those flags to initial state.
Unfortunately this behavior needs do be copied from a legacy system that we need to mimic at some level. In a future release we plan to avoid decorating the object and to implement CQRS style of communication, but that's not doable now.
My first idea to cope with this issue was to have a separate cache we could write to objects that are decorated and such cache would server a purpose of a write queue. A CacheStore would be associated with this cache. And the read cache would be updated with the same value but after putting to write cache and after resetting the flags.
I have been looking at MapTrigger but that doesn't solve my issue due to the place of MapTrigger in the chain of operations - before CacheStore.
It is possible to subclass and customize ReadWriteBackingMap or LocalCache used as internal map inside of it. This way you cloud override put method and make required transformation, you cloud also modify content of backing map directly. This technique is rarely used and messy, but it alows you to implement very non-trivial BM behavior.
With backing listener you should also be aware of global cache lock issue http://blog.ragozin.info/2012/12/coherence-101-beware-of-cache-listeners.html.
You could try asynchronously call out from your cachestore (e.g. by ThreadPoolExecutor) to update your cache entry after it has been persisted. You might want to use optimistic locking at the cache entry level, or even table row within the cache entry so as not to lose updates that came in during the persistence/status update process. Of course the status update itself would cause another call to your CacheStore, but with rows no longer marked for persistence so you could ignore those.
Done right, this would allow asynch persistence and should work even with coalesced updates. The asynch step in updating status is necessary as you would not be able to re-entrantly call the cache service from within the CacheStore.