Hi I want to add an expiry time to the redis cache.
I have added spring.cache.redis.time-to-live=1m.
, but its not working.
I am using Jedis connection factory , for connection
please some thing , new to Redis.
Tried to create some beans as I got from google, but not working.
To add an expiry time to Redis cache in Spring Boot, you can set the "spring.cache.redis.time-to-live" property in the application.properties file as you have done. This property specifies the default time-to-live for cache entries.
However, there are a few things to check if it's not working as expected:
Ensure that you have the Spring Boot Redis dependency in your pom.xml or build.gradle file.
Check if the Redis cache is enabled by adding the #EnableCaching annotation to your Spring Boot application class.
Check if the RedisConnectionFactory is properly configured. In your case, you are using JedisConnectionFactory. You can create a bean for the RedisConnectionFactory as follows:
#Bean
public RedisConnectionFactory redisConnectionFactory() {
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
// set the Redis server host and port
jedisConnectionFactory.setHostName("localhost");
jedisConnectionFactory.setPort(6379);
jedisConnectionFactory.afterPropertiesSet();
return jedisConnectionFactory;
}
Ensure that the RedisTemplate is properly configured. You can create a bean for RedisTemplate as follows:
#Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
// set the key and value serializer
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
Note that in the above example, I'm using the GenericJackson2JsonRedisSerializer for serializing the values. You can change this to any other serializer that suits your needs.
Once you have the RedisConnectionFactory and RedisTemplate beans configured properly, Spring Boot should automatically apply the time-to-live property to the cached values.
If the issue still persists, you can try setting the TTL for a specific cache using the #Cacheable annotation as follows:
#Cacheable(value = "myCache", key = "#key", unless = "#result == null", cacheManager = "cacheManager", cacheManagerCustomizers = MyCacheManagerCustomizer.class)
public Object getCachedData(String key) {
// your code to retrieve the data from the database or any other source
}
In the above example, I have set the TTL for the "myCache" cache using the MyCacheManagerCustomizer class. You can implement this class to customize the cache manager as per your requirements.
I hope this helps you to add an expiry time to Redis cache in your Spring Boot application.
Related
I have a simple method that connects to an external service and I want to cache its result
#Cacheable(cacheNames = "myCache", key = "#token")
public String getUserByToken(String token) {
return externalService.getUserFromToken(token);
}
Right now this is my custom CacheManager config because i need different TTL for different cache key.
#Configuration
#EnableCaching
public class CacheConfiguration extends CachingConfig {
#Autowired
private LettuceConnectionFactory lettuceConnectionFactory;
#Primary
#Bean
public CacheManager cacheManager() {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
CacheManager cacheManager = RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(lettuceConnectionFactory)
.cacheDefaults(redisCacheConfiguration)
.withCacheConfiguration("myCache",
redisCacheConfiguration.entryTtl(Duration.ofMinutes(5)))
.withCacheConfiguration("someOtherCache",
redisCacheConfiguration.entryTtl(Duration.ofMinutes(10)))
.build();
return cacheManager;
}
Right now I have a single lettuceConnectionFactory which is simply the bean created by Spring AutoConfigure stuff and uses my Redis primary Read / Write endpoint.
However I would like to improve throughput and planning to create 2 separate lettuce connection factory bean. One that will use my Redis primary read / write endpoint and an other lettuceReadConnectionFactory that will use my Redis read only endpoint.
I would like to use the lettuceReadConnectionFactory exclusively for read operation.
Is there a way somehow to still use #Cacheable and have it use a different cacheManager to read and write ?
The #Cacheable annotation takes a cacheManager attribute, you could create two different named CacheManager beans and pass your customized managers to it.
How do I create and use the Redis connection that spring-boot-starter-data-redis creates? It doesn't seem like there is a Bean for RedisClient created by the default auto configuration so I'm not sure of the best way to do this.
The documentation does state that in this case you need to create the StorageProvider yourself which is fine, but can you reuse what Spring Boot has already created. I believe this would need to be a pooled connection which you would also need to enable through Spring Boot.
RedisTemplate offers a high-level abstraction for Redis interactions:
https://docs.spring.io/spring-data/data-redis/docs/current/reference/html/#redis:template
Redis autoconfiguration :
#AutoConfiguration
#ConditionalOnClass({RedisOperations.class})
#EnableConfigurationProperties({RedisProperties.class})
#Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
public RedisAutoConfiguration() {
}
#Bean
#ConditionalOnMissingBean(
name = {"redisTemplate"}
)
#ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
#Bean
#ConditionalOnMissingBean
#ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
return new StringRedisTemplate(redisConnectionFactory);
}
}
Here you can find the corresponding configuration properties(including connection pool default configuration).
Simple implementation example :
https://www.baeldung.com/spring-data-redis-tutorial
I need to configure request timeouts in code for all routes. I know global timeouts can be configured via following properties in application.properties, but how can they be configured in code?
spring.cloud.gateway.httpclient.connect-timeout=1000
spring.cloud.gateway.httpclient.response-timeout=5s
I have looked at GatewayAutoConfiguration how timeouts are configured by default. HttpClientProperties holds both properties, however it cannot be overwritten.
#Bean
public HttpClientProperties httpClientProperties() {
return new HttpClientProperties();
}
Can this be done in code?
I solved my problem. I created my own bean and used annotation #Primary to be able to create a separate bean with the same type. GatewayAutoConfiguration now uses my bean instead of the default bean.
#Bean
#Primary
public HttpClientProperties overwrittenHttpClientProperties() {
HttpClientProperties p = new HttpClientProperties();
p.setConnectTimeout(3000);
p.setResponseTimeout(Duration.ofMillis(10000));
return p;
}
I want to use Lettuce as a Redis Client, which is the default dependency for spring-boot-starter-data-redis-reactive. However I am inheriting Jedis as a dependency from another component written as pure Java code (no Spring). This is resulting in a conflict when initializing LettuceConnectionFactory due to presence of JedisConnectionFactory.
How can I keep Jedis in dependency for other component's use while ensuring that LettuceConnectionFactory is initialised for my own code? The main reason for using LetticeConnectionFactory is reactive programming in my service.
Both the connection factories are configured for initialization via RedisAutoConfiguration with no option of prioritisation.
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/RedisAutoConfiguration.java
You could override RedisConnectionFactory by creating your own #Configuration class and adding new #Bean in it.
For example:
#Bean
RedisConnectionFactory myLettuceConnectionFactory() {
// your setup....
new LettuceConnectionFactory();
}
and then use myLettuceConnectionFactory bean to setup RedisTemplate #Bean
#Bean
public RedisTemplate<String, Object> redisTemplate() {
final RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(myLettuceConnectionFactory());
// other settings...
return template;
}
How to I configure the Mongo database bean? The bean is initialized by the MongoDB driver somehow with somethings pre-configured. I can't get the bean using mongoClient.getDatabase() because the database name either comes from the connection uri or just the standard property. And I can't define a new bean to update the old one like this public MongoDatabase mongoDatabase(MongoDatabase database) because that causes a ban definition cycle loop. What do I do?
Not entirely relevant to the question, but here's my intention:
What I trying to do is add custom Conventions introduced in MongoDB Driver version 3.6.
http://mongodb.github.io/mongo-java-driver/3.6/bson/pojos/
I know that spring data mongodb uses an older version, so I just replaced it with the newer one.
You need to take care of couple of things if you wish to configure MongoTemplate Or MongoDatabase yourself.
You need to disable spring boot's Mongo Auto Configuration. You can achieve this as show below.
#SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
You have to create MongoTemplate or MongoDatabase bean and register it with Spring application context(using #Bean).
#Bean
public MongoDbFactory mongoDbFactory() throws Exception {
ServerAddress server = new ServerAddress(host,port);
MongoClientOptions.Builder builder = MongoClientOptions.builder();
CodecRegistry codecRegistry = CodecRegistries.fromRegistries(CodecRegistries.fromCodecs(new XYZCodec(..)),
MongoClient.getDefaultCodecRegistry());
builder.codecRegistry(codecRegistry).build();
MongoClientOptions options = builder.build();
MongoClient mongoClient = new MongoClient(server,options);
return new SimpleMongoDbFactory(mongoClient, mongoDataBase);
}
Replace XYZCodec with the codec you want.