Reputation: 113
I am using Spring Cache abstraction based on annotations in my service.
I want to add a custom prefix to the key when added to the cache.
I created a constant and tried to add them to the methods as below.
private static final String CACHE_KEY_PREFIX="user";
@Cacheable(value = "users", key = "{ CACHE_KEY_PREFIX,#userId }")
@GetMapping("/{userId}")
public User getUser(@PathVariable String userId) {
LOG.info("Getting user with ID {}.", userId);
return userRepository.findOne(Long.valueOf(userId));
}
@CacheEvict(value = "users",key="{ CACHE_KEY_PREFIX,#userId }" )
@DeleteMapping
public void deleteUserByID(@PathVariable Long userId) {
LOG.info("deleting person with id {}", userId);
userRepository.delete(userId);
}
But, I get the stacktrace as below.
2018-06-12 13:35:48.911 ERROR 8728 --- [nio-8090-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.expression.spel.SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: 'hash(#)'] with root cause
org.springframework.expression.spel.SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: 'hash(#)'
at org.springframework.expression.spel.standard.InternalSpelExpressionParser.doParseExpression(InternalSpelExpressionParser.java:129)
at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:60)
Since I have multiple methods I do not want to hardcode the custom prefix in every method annotation.
Is there a way to add a custom prefix and avoid the exception I am seeing.
Upvotes: 2
Views: 5253
Reputation: 415
One of the ways is to create a custom RedisCacheConfiguration
bean. Note that a semicolon just a common delimiter between the parts of a key, it has no special purpose.
A common prefix can be useful in a shared Redis instance to easily differentiate between the caches from different sources (example, from different microservices):
@Configuration
@EnableCaching
public class MyCacheConfig {
@Bean
public RedisCacheConfiguration cacheConfiguration() {
return RedisCacheConfiguration.defaultCacheConfig()
.prefixCacheNameWith("myprefix:");
}
}
Upvotes: 0
Reputation: 426
To use a constant in the annotation, you could include it as a fixed String like this:
@Cacheable(value = "users", key = "{'" + CACHE_KEY_PREFIX + "', #userId}")
@GetMapping("/{userId}")
public User getUser(@PathVariable String userId) {
LOG.info("Getting user with ID {}.", userId);
return userRepository.findOne(Long.valueOf(userId));
}
In this case, the compiler will resolve the value of attribute key
to {'user', #userId}
.
Upvotes: 3