How to set an expiration time for the cache?

@Override
@Transactional
public UserDetails loadUserByUsername(String username)  {
    log.debug("Load user {}", username);
    UserDetails userDetails = userService.findUserDetailsByName(username).get();
    return userDetails;
}

When the user authorizes, the loadUserByUsername method calls the findUserDetailsByName method from the userService. In this method, when authorizing a user, Spring writes the user's data to cache and does not contact the database the next time.

My task is to delete this cache within 10 minutes, so that Spring can re-enter the database, since roles can be changed. I know a solution using @Scheduled, but I think the given approach is wrong. Can you suggest an acceptable option for clearing the cache every 10 minutes?

@Component
@Slf4j
public class Customizer implements CacheManagerCustomizer<ConcurrentMapCacheManager> {
    @Override
    public void customize(ConcurrentMapCacheManager cacheManager) {
        cacheManager.setCacheNames(List.of(Caches.UD_CACHE));
    }

    @CacheEvict(allEntries = true, value = {Caches.UD_CACHE})
    @Scheduled(fixedDelay = 10 * 60000)
    public void reportCacheEvict() {
        log.info("Flush cache " + Caches.UD_CACHE + " at " + new Date());
    }
}
    private final Cache userDetailsCache;
    public UserService(CacheManager cacheManager) {
        this.userDetailsCache = cacheManager.getCache(Caches.USER_DETAILS_CACHE);
    }
    public Optional<UserDetails> findUserDetailsByName(String username) {
        ValueWrapper v= userDetailsCache.get(username);
        if (v== null) {
            Optional<UserDetails> userDetailsOpt =
                userRepository.findOne(QUser.user.userName.eq(username)).map(UserService::createFrom);
            userDetailsOpt.ifPresent(u -> userDetailsCache.put(username, u));
            return userDetailsOpt.map(u -> withUserDetails(u).build());
        } else {
            return Optional.ofNullable((UserDetails) v.get()).map(u -> withUserDetails(u).build());
        }
    }
public final class Caches {
    public static final String UD_CACHE = "udCache";
}

Upvotes: 2

Views: 1615

Answers (1)

Ren&#233; Link
Ren&#233; Link

Reputation: 51373

In you example you use fixedDelay, but since you want to clear the cache every 10 mins you should use a fixedRate.

 public class Customizer implements CacheManagerCustomizer<ConcurrentMapCacheManager>{
  
     @Override
     public void customize(ConcurrentMapCacheManager cacheManager) {
         cacheManager.setCacheNames(List.of(Caches.UD_CACHE));
     }

     @CacheEvict(allEntries = true, value = {Caches.UD_CACHE})
     @Scheduled(fixedRate = 10 * 60000)
     public void evictUDCache() {
        log.info("Flush cache " + Caches.UD_CACHE + " at " + new Date());
     }
 }

EDIT

thanks. but I'm interested in the option without @Scheduled

You can inject the TaskScheduler and then use it when you need it.

TaskScheduler taskScheduler = ....;

Cache udCache = cacheManager.getCache(Caches.UD_CACHE);  
Duration clearCacheInterval = Duration.of(10L, ChronoUnit.MINUTES);

taskScheduler.scheduleAtFixedRate(udCache::clear, clearCacheInterval);

or schedule with a fixed delay

taskScheduler.scheduleWithFixedDelay(udCache::clear, clearCacheInterval);

Upvotes: 1

Related Questions