Sam Brannen opened SPR-11400 and commented

Status Quo

Spring's Cache API currently has a put(Object key, Object value) method, but there is no form of thread-safe putIfAbsent(Object key, Object value) method (i.e., to avoid subsequent thread-unsafe if get() == null then put() calls).

Deliverables

  1. [x] Introduce a putIfAbsent(Object key, Object value) method in org.springframework.cache.Cache and corresponding implementations.

Temporary Work-around

If one needs putIfAbsent() behavior now, consider accessing the underlying cache implementation via Cache.getNativeCache() and then invoking putIfAbsent() (or similar) on the native cache using the native API if available.


Affects: 3.0 GA

Comment From: spring-projects-issues

Stéphane Nicoll commented

Sam, do you need a return type for that method? that is either a boolean indicating if the value was set or the value that was already set. The reason why I am asking is that TransactionAwareCacheDecorator would have a hard time to fulfil this contract when running as part of a transaction.

Right now the method does not return anything. Let me know if that fits with what you had in mind.

Comment From: spring-projects-issues

Sam Brannen commented

Hi Stéphane Nicoll,

Sorry about the belated reply here.

Actually, I was thinking the method could either return a boolean flag (with true indicating success) like with javax.cache.Cache or the actual value like with Ehcache and Java's ConcurrentMap, preferably the actual value.

For example, the API for ConcurrentMap defines the return value as follows:

Returns the previous value associated with the specified key, or null if there was no mapping for the key. (A null return can also indicate that the map previously associated null with the key, if the implementation supports null values.)

Maybe it's not feasible (or even possible) to return the actual value (since we support so many underlying cache implementations with differing APIs). So in the very least, I think it would be nice to return a boolean flag (again if possible).

Thanks,

Sam

Comment From: spring-projects-issues

Stéphane Nicoll commented

putIfAbsent has been added to the Cache abstraction SPI with an Object value that is either null if this call associated the key in the cache or the existing object, if the key was already associated. Most cache providers do support this method signature, only the JCache API returns a boolean value. Guava returns the value that is set so there's additional logic to return the proper value.

After discussing this with Jürgen, there's no real benefit of getting a boolean (from an atomic standpoint, uses would like to get the value they have to manage).

The transaction proxy cannot support this feature properly so the Javadoc has been updated and putIfAbsent is immediately putting the value, even when a transaction is running.