8

Hi I have problem with clean cache when method is executed. Here is my configuration and caches methods:

@Configuration
@EnableCaching
@AutoConfigureAfter(value = {MetricsConfiguration.class, DatabaseConfiguration.class})
@Profile("!" + Constants.SPRING_PROFILE_FAST)
public class CacheConfiguration {

    private final Logger log = LoggerFactory.getLogger(CacheConfiguration.class);
    public static final String STOCK_DETAILS_BY_TICKER_CACHE = "stockDetailsByTickerCache";
    public static final String RSS_NEWS_BY_TYPE_CACHE = "rssNewsByTypeCache";

    @Bean
    public CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        List<Cache> caches = new ArrayList<Cache>();
        caches.add(new ConcurrentMapCache(STOCK_DETAILS_BY_TICKER_CACHE));
        caches.add(new ConcurrentMapCache(RSS_NEWS_BY_TYPE_CACHE));
        cacheManager.setCaches(caches);
        return cacheManager;
    }
}

This method i want to cache:

@Cacheable(cacheNames = CacheConfiguration.RSS_NEWS_BY_TYPE_CACHE, key = "#type")
    public ResponseEntity<List<NewsDetailsDTO>> getLatestNewsMessageByType(RssType type) {
        Pageable pageable = new PageRequest(0, 5, Sort.Direction.DESC, "createdDate");
        List<NewsMessage> latestNewsMessage = newsMessageRepository.findByType(type, pageable).getContent();
        return new ResponseEntity<List<NewsDetailsDTO>>(mapToDTO(latestNewsMessage), HttpStatus.OK);
    }

On execution of this method i would like to clean cache by type:

@CacheEvict(cacheNames={CacheConfiguration.RSS_NEWS_BY_TYPE_CACHE}, beforeInvocation = true, key = "#news.type")
    public void save(NewsMessage news) {
        newsMessageRepository.save(news);
    }

And NewsMessage object looks like:

@Entity
@Table(name = "NEWS_MESSAGE")
public class NewsMessage extends ChatMessage {

    <other fileds>

    @NotNull
    @Enumerated(EnumType.STRING)
    private RssType type;
}

The cache thing works fine, by the first time there is a query to DB by second and next the data is fetch from cache. Problem is when I update data the @CacheEvict does not clean the cache. I was trying to clean all cache using this annotation: @CacheEvict(cacheNames={CacheConfiguration.RSS_NEWS_BY_TYPE_CACHE}, allEntries = true) But it also does not work. Could you help me?

3 Answers 3

8

From where do you call the save() method?

In your own answer it looks like you have moved the annotations to another class/interface to invoke the proxy object of that class/interface (btw annotations should generally not be used in interfaces, because they often don't get catched with default configuration).

Therefore my question: do you know the spring aop proxy? You have to call annotated methods from methods outside your MessageRepository class to invoke the proxy object.

General documentation for that is here: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#aop-understanding-aop-proxies

or with examples here http://spring.io/blog/2012/05/23/transactions-caching-and-aop-understanding-proxy-usage-in-spring

1
  • You are right, i miss understand the concept of spring proxy. Thanks for links.
    – Pulkownik
    Commented May 5, 2016 at 9:43
2

I found the workaround for my problem. I had to moved the annotation upper to the spring data jpa interace.

public interface NewsMessageRepository extends JpaRepository<NewsMessage, Long> {

    @CacheEvict(cacheNames = {CacheConfiguration.RSS_NEWS_BY_TYPE_CACHE}, beforeInvocation = true, key = "#p0.type")
    NewsMessage save(NewsMessage news);
}

Now it is working as i expected, but still have no idea why it did not work in my service. Maybe because my services implements two interfaces?

@Service
public class NewsMessageService implements RssObserver, NewsMessageServiceable {
}
0

You need a public RssType getType() method in your NewsMessage class. The key expression "#news.type" in your @CacheEvict annotation is expecting either a public field named "type" or a public getter method named "getType".

1
  • I had the following getter: public RssType getType() { return type; } So it should works fine. But please notice that the cacheEvict with allEntires=true also does not work.
    – Pulkownik
    Commented May 3, 2016 at 17:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.