I am working on an OTP (one-time password) provider microservice and I want to cache the OTPs in Couchbase and retrieve them for a given key. I am able to achieve this using the following pieces of code. But I am not able to implement one final feature, which is, the OTP should be short-lived and should get automatically evicted from the cache after a certain configurable interval.
I am using the following dependencies -
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-couchbase</artifactId>
</dependency>
and I have configured a CacheConfig as follows -
@Configuration
public class CacheConfig {
@Value("${couchbase.url}")
private String url;
@Value("${couchbase.username}")
private String username;
@Value("${couchbase.password}")
private String password;
@Value("${couchbase.bucket}")
private String bucket;
public static final String CACHE_NAME ="otp-cache";
@Bean(destroyMethod = "disconnect")
public Cluster cluster() {
return Cluster.connect(url, username, password);
}
@Bean
public CacheManager cacheManager() {
return CouchbaseCacheManager.create(new SimpleCouchbaseClientFactory(cluster(), bucket, null));
}
}
finally in my service class, where i generate the OTP, I am using the @Cacheable annotation as follows -
@Cacheable(cacheNames = CacheConfig.CACHE_NAME, key = "'provider_'+#key")
@Override
public Integer generateOTP(String key) {
StringBuilder generatedOTP = new StringBuilder();
SecureRandom secureRandom = new SecureRandom();
LOGGER.info("generating OTP for provider(not from cache) - "+key);
try {
secureRandom = SecureRandom.getInstance(secureRandom.getAlgorithm());
for (int i = 0; i < LENGTH_OF_OTP; i++) {
generatedOTP.append(secureRandom.nextInt(9));
}
} catch (NoSuchAlgorithmException e) {
LOGGER.error("exception occurred in generating OTP");
}
return Integer.parseInt(generatedOTP.toString());
}
I have come across some solutions which suggests using the @CacheEvict annotation with a @Scheduled method, but it will clear the entire cache and not just expired entries. I have also tried wrapping the response of the @Cacheable method in a serializable object and used the @Document(expiryExpression = and @Expiry annotation, but that does not work either, additionally, I get some class cast exception when the object is fetched from the cache and spring tries to deserialize it to the pojo class.
I also see this property using my IDE's auto-suggestion in application-properties file spring.cache.couchbase.expiration=, but this doesn't work either.
How do I set an expiration time for each otp cached in the couchbase bucket?
For a lifetime of 60 minutes, use
CouchbaseCacheConfiguration.defaultCacheConfig().entryExpiry(Duration.ofMinutes(60))
https://docs.spring.io/spring-data/couchbase/reference/couchbase/caching.html