I'm using Spring Boot and EhCache to develop a calendar application. I'm trying to cache the following method:
@Override
@Cacheable(value = "concerts")
public List<Event> getEvents(String eventsForUser, Date startDate, Date endDate) throws Exception {
return fetchEventsFromTheServer(eventsForUser, startDate, endDate);
}
The challenge is I would like to manipulate returned cached result. For example, check if there is cache for given dates but for a different user and then return it instead (as long as both users meet certain criteria).
So, before returning a result I would like:
I think the best would be to create a custom Cache Manager which will do all the manipulation with cached concert and use default auto configured cache for all other methods, but I can't get my custom manager to work and didn't find any good example on how to implement a custom CacheManager.
Here is what I have:
Application.java:
@SpringBootApplication
@ComponentScan
@EnableCaching
@EnableScheduling
public class SpringBootWebApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(SpringBootWebApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(applicationClass);
}
private static Class<SpringBootWebApplication> applicationClass = SpringBootWebApplication.class;
@Bean(name = "eventsCacheManager")
public EventsCacheManager eventsCacheManager() {
return new EventsCacheManager();
}
@Primary
@Bean(name = "cacheManager")
public CacheManager cacheManager() {
return new EhCacheCacheManager(ehCacheCacheManager().getObject());
}
@Bean
public EhCacheManagerFactoryBean ehCacheCacheManager() {
EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean();
cmfb.setConfigLocation(new ClassPathResource("ehcache.xml"));
cmfb.setShared(true);
return cmfb;
}
}
EventsCacheManager.java
@Component
public class EventsCacheManager implements CacheManager {
@Override
public Cache getCache(String s) {
return null;
}
@Override
public Collection<String> getCacheNames() {
return null;
}
}
EventsCacheManager.java - how to implement it?
@Component
public class EventsCacheManager implements CacheManager {
@Override
public Cache getCache(String s) {
return null;
}
@Override
public Collection<String> getCacheNames() {
return null;
}
}
I would really appreciate if someone can give me an example on how I should implement my custom CacheManager
I did not spend much time thinking about your requirements/use case, but I do think a custom CacheManager
would work in this situation, assuming the "custom" CacheManager
logic is correct.
So, by default, Spring looks for a bean in the context with the name "cacheManager" and uses it for all cached operations. In your configuration, you clearly have 2 "CacheManagers" defined...
@Bean(name = "eventsCacheManager")
public EventsCacheManager eventsCacheManager() {
return new EventsCacheManager();
}
@Primary
@Bean(name = "cacheManager")
public CacheManager cacheManager() {
return new EhCacheCacheManager(ehCacheCacheManager().getObject());
}
I.e. the "eventsCacheManager" (custom) and "cacheManager" (standard). Indeed, you even marked the "cacheManager" as primary (using the @Primary
annotation). Of course, had you not done that, Spring would certainly have complained since more than 1 bean of a given type (i.e. CacheManager
) was found in the context when performing auto-wiring (which defaults to auto-wire by type).
So, in order to call out which cache management strategy (i.e. CacheManager
) to use at runtime with a particular service call, you also need to tell Spring which CacheManager
(aka strategy) to use, like so...
@Override
@Cacheable(value = "concerts", cacheManager="eventsCacheManager")
public List<Event> getEvents(String eventsForUser, Date startDate, Date endDate) throws Exception {
return fetchEventsFromTheServer(eventsForUser, startDate, endDate);
}
I.e. using the cacheManager
attribute in the @Cacheable
annotation to indicate which caching strategy to use.
See Spring's Reference Doc on Custom cache resolution for more details.
Hope this helps get you going.