Introduction:
Optimizing API performance is always crucial for delivering exceptional user experiences. One effective strategy to achieve this goal is response caching, where frequently requested responses are stored and served directly from the cache. Redis, a lightning-fast in-memory data store, serves as an excellent caching solution. In this blog post, we'll explore how we leveraged Redis Cache Manager in a Spring Boot application to implement response caching effectively for a huge list of master data specific endpoints that had heavy traffic in production environment. Additionally, we'll introduce a sample Plain Old Java Object (POJO) called Lookup
and the Office
class to illustrate seamless integration with our caching mechanism.
Why Response Caching?
Response caching significantly reduces server load and improves response times by serving cached responses directly from memory. This approach is particularly beneficial for endpoints handling static or infrequently changing data, leading to enhanced performance and scalability.
Setting Up Redis Cache Manager in Spring Boot:
Let's start by configuring Redis Cache Manager in our Spring Boot application to unlock the full potential of Redis for response caching.
1. Dependency Setup:
Ensure that you have the necessary dependencies in your pom.xml
or build.gradle
file:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2. Configuration:
Create a configuration class to set up Redis Cache Manager:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@Configuration
public class CacheConfig {
@Bean
public RedisCacheConfiguration redisCacheConfiguration() {
return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(10)) // Cache entries expire after 10 minutes
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
}
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory, RedisCacheConfiguration config) {
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(config)
.build();
}
}
In this configuration, we set the default cache entry TTL (time-to-live) to 10 minutes and configure serializers for keys and values.
3. Caching Responses:
Now, let's cache responses of specific endpoints in our Spring Boot application. We'll use the @Cacheable
annotation to cache the responses.
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HRMSController {
private final OfficeService officeService;
@GetMapping("/office/{stateDepartmentId}")
@Cacheable(value = "HRMS_CACHE", key = "#root.methodName+#stateCode+#stateDepartmentId")
public List<Office> getOfficeByStateDepartmentId(
@RequestHeader(name = X_STATE_CODE) String stateCode,
@PathVariable String stateDepartmentId) {
log.info("Fetching office by state department ID: {}", stateDepartmentId);
return officeService.getOfficeByStateDepartmentId(stateCode, stateDepartmentId);
}
}
In this example, we're using the @GetMapping
annotation to map the endpoint /office/{stateDepartmentId}
to the getOfficeByStateDepartmentId
method. This method retrieves a list of offices based on the state department ID.
We've also added the @Cacheable
annotation to cache the response of this method using Redis Cache Manager. The value
attribute specifies the cache name (HRMS_CACHE
), and the key
attribute generates a unique cache key based on the method name, state code, and state department ID.
Introducing POJOs: Lookup and Office
Now, let's introduce two sample Plain Old Java Objects (POJOs) - Lookup
and Office
- to illustrate seamless integration with our caching mechanism:
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@Getter
@SuperBuilder
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "@class")
@NoArgsConstructor
public class Lookup {
private long id;
private String code;
private String name;
private String nameInLocal;
private boolean active;
}
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@Getter
@SuperBuilder
@NoArgsConstructor
public class Office extends Lookup {
private String stateDepartmentId;
private int officeTypeId;
private int districtId;
private int lbId;
}
Please pay attention to the JsonTypeInfo.Id.CLASS
, this might be required if you face serialization error. Otherwise it can be skipped.
Conclusion:
By incorporating Redis Cache Manager in our Spring Boot application and leveraging response caching, we can significantly enhance performance and scalability. Response caching, powered by Redis, reduces response times and server load by serving cached responses directly from memory. Additionally, introducing POJOs like Lookup
and Office
enables seamless integration with our caching mechanism, further optimizing our application's performance.
In summary, by adopting response caching and leveraging powerful caching solutions like Redis in conjunction with POJOs, we can create high-performance Spring Boot applications that deliver exceptional user experiences. Embrace the power of response caching and elevate your application's performance today!