]
Dan Berindei commented on ISPN-3128:
------------------------------------
[~sebastian.laskawiec] as a partial solution we could use {{putForExternalRead()}} in
{{SpringCache.get(Object, Callable)}} for invalidation caches. [~matlach]'s workaround
analyzing the stack trace seems too heavy-weight.
We can also raise a bug in Spring to tell caches what annotation triggered the operation.
But one can already use {{SpringAOP}} to call {{putForExternalRead()}} if the method has a
custom annotation (say {{@LocalCacheable}}), so it's probably not going to be a
priority for them.
Better support for (Spring) read caching
----------------------------------------
Key: ISPN-3128
URL:
https://issues.jboss.org/browse/ISPN-3128
Project: Infinispan
Issue Type: Feature Request
Components: Spring Integration
Affects Versions: 5.3.0.Beta2
Environment: Spring 3.1+
Reporter: Mike Noordermeer
Assignee: Sebastian Ćaskawiec
We're having a bit of an issue using Infinispan as backing cache for Spring's
Caching annotations. The reasons are clear, but I haven't found a proper solution yet.
I thought I would describe the issues in a feature request, so we can try to make the
necessary changes to fix the situation.
As already described in [the
forums|https://community.jboss.org/thread/201086], an
Infinispan cache in invalidation mode sends an invalidation message to other cache nodes
if something is put into the cache. This conflicts with Spring's idea of
{{@Cacheable}} annotations, which are ment to provide read caching for methods. Imagine
the following scenario:
- Method A is annotated with {{@Cacheable}}, backed by a cache in invalidation mode
- Node X calls Method A, the method is executed and the return value is locally cached
(and an invalidation message is sent to Node Y)
- Node Y calls Method A, the method is executed and the return value is locally cached,
*also, the cache of Node X is invalidated*
- Node X calls Method A and has to execute the method again, since its cache is gone,
etc... etc...
The reason we want to be able to invalidate the read cache, is because if the application
executed an update method for the underlying data (usually marked with {{@CacheEvict}} or
{{@CachePut}}) we *do* want to invalidate the other ndoes.
In Infinispan, this problem can be solved by caching using
{{cache.putForExternalRead()}}. That will not invalidate other caches on a put, but will
invalidate the cache when asked explicitly. However, simply changing {{put()}} to
{{putForExternalRead()}} in {{SpringCache}} leads to a couple of other issues:
- This is probably not the behaviour everyone wants (people that do not use Spring
annotations, but expect the usual Infinispan behaviour).
- Changing {{put()}} to {{putForExternalRead()}} would break the expected {{@CachePut}}
behaviour (a new value is generated, so the old values should be invalidated), but it
would fix {{@Cacheable}} behaviour.
Maybe there should be an option in the factory bean to switch between {{put()}} and
{{putForExternalRead()}}? Maybe Spring should change or amend its interface so we can
differentiate between calls coming from {{@CachePut}} and calls coming from
{{@Cacheable}}? An other option is to make the invalidation behaviour configurable in
Infinispan (that's the way Ehcache handles this issue, you can choose if puts or
updates should be replicated, or just replicate invalidations).