Reputation: 853
@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
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