I have a generic listener for most of my caches and I do some logging when an event occurs. The problem is that I don't know which cache is behind the event that I caught. How do I get the cache's alias (i.e. name) ?
I have:
The configuration class (it reads in the .xml file ehcache.xml)
@Configuration
@EnableCaching
public class CacheConfig {
@Autowired
private javax.cache.CacheManager cacheManager;
}
application.yml
spring:
cache:
jcache:
config: classpath:ehcache.xml
ehcache.xml (in src/main/resources)
...
<cache alias="myCache">
<listeners>
<listener>
<class>com.iznogoud.cache.DefaultListener</class>
<event-firing-mode>ASYNCHRONOUS</event-firing-mode>
<event-ordering-mode>UNORDERED</event-ordering-mode>
<events-to-fire-on>CREATED</events-to-fire-on>
<events-to-fire-on>EXPIRED</events-to-fire-on>
<events-to-fire-on>EVICTED</events-to-fire-on>
<events-to-fire-on>REMOVED</events-to-fire-on>
<events-to-fire-on>UPDATED</events-to-fire-on>
</listener>
</listeners>
<expiry>
<ttl unit="seconds">10</ttl>
</expiry>
<heap unit="entries">10000</heap>
</cache>
My generic Listener class, com.iznogoud.cache.DefaultListener:
@Component
public class DefaultListener implements CacheEventListener<Object, Object> {
private static final Logger LOGGER...
public DefaultListener() {}
@Override
public void onEvent(CacheEvent<?, ?> cacheEvent) {
String cacheAlias = "dont-know!";
String key = cacheEvent.getKey().toString();
String = cacheEvent.getOldValue()==null?"null":cacheEvent.getOldValue().toString();
String = cacheEvent.getNewValue()==null?"null":cacheEvent.getNewValue().toString();
LOGGER.debug("Cache {}, EventType: {} : Key: {} | | value {} -> {}",
cacheAlias, cacheEvent.getType(), key, oldValue, newValue);
}
Here's a somewhat-of-a-hack answer, but it works under I'm-testing-it-myself conditions:
In the @Configuration file where you define the cache manager add an init() method that constructs a map of the caches, and make the map public.
@Configuration
@EnableCaching
public class CacheConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(CacheConfig.class);
@Autowired
private javax.cache.CacheManager cacheManager;
/** a mapping that enables Cache Listeners to get the name of the Cache when an event arrives **/
public static HashMap<String, String> cacheNamesMap;
/** ehCache Listeners don't know which cache they are dealing with. (unless you have a listener class for each cache, ugh)
But the cache manager here has all the aliases.
So, make a map available between the instance of a cache (via .toString()) and it's name.
The listeners use this map to find the alias of the cache that triggered the event.
*/
@PostConstruct
private void init() {
cacheNamesMap = new HashMap<>();
List<String> cacheNames = new ArrayList<String>();
for (String nextName : cacheManager.getCacheNames()) {
// use a key based on the underlying ehCache class, not the jCache class, the listeners are ehCache specific
Cache nextCache = cacheManager.getCache(nextName).unwrap(org.ehcache.Cache.class);
cacheNamesMap.put(nextCache.toString(), nextName);
}
LOGGER.debug("{} caches in cacheNamesMap.", cacheNamesMap.size());
LOGGER.debug(" keys: {}", cacheNamesMap.keySet());
}
Then access the map in your listener.
@Override
public void onEvent(CacheEvent<?, ?> cacheEvent) {
Cache cache = cacheEvent.getSource();
String cacheAlias = CacheConfig.cacheNamesMap.get(cache.toString());
...
Maybe it's not the most industrial waterproof solution but it works for me. getSource() is, unfortunately, deprecated.