Context:
- Getting Started
- Maven Dependencies
- Redis Configuration
- Spring Service
- Docker & Docker Compose
- Build & Run Application
- Endpoints with Swagger
- Demo
In this project, I used Redis for caching with Spring Boot. When you send any request to get all customers or customer by id, you will wait 3 seconds if Redis has no related data.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
@EnableCaching
public class RedisConfig {
@Autowired
private CacheManager cacheManager;
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private int redisPort;
@Bean
public RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Serializable> template = new RedisTemplate<>();
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
RedisCacheConfiguration redisCacheConfiguration = config
.serializeKeysWith(
RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()));
RedisCacheManager redisCacheManager = RedisCacheManager.builder(factory).cacheDefaults(redisCacheConfiguration)
.build();
return redisCacheManager;
}
}
Spring Boot Customer Service Implementation will be like below class. I used Spring Boot Cache @Annotaions for caching.
These are:
@Cacheable
@CacheEvict
@Caching
@CachceConfig
@Service
@CacheConfig(cacheNames = "customerCache")
public class CustomerServiceImpl implements CustomerService {
@Autowired
private CustomerRepository customerRepository;
@Cacheable(cacheNames = "customers")
@Override
public List<Customer> getAll() {
waitSomeTime();
return this.customerRepository.findAll();
}
@CacheEvict(cacheNames = "customers", allEntries = true)
@Override
public Customer add(Customer customer) {
return this.customerRepository.save(customer);
}
@CacheEvict(cacheNames = "customers", allEntries = true)
@Override
public Customer update(Customer customer) {
Optional<Customer> optCustomer = this.customerRepository.findById(customer.getId());
if (!optCustomer.isPresent())
return null;
Customer repCustomer = optCustomer.get();
repCustomer.setName(customer.getName());
repCustomer.setContactName(customer.getContactName());
repCustomer.setAddress(customer.getAddress());
repCustomer.setCity(customer.getCity());
repCustomer.setPostalCode(customer.getPostalCode());
repCustomer.setCountry(customer.getCountry());
return this.customerRepository.save(repCustomer);
}
@Caching(evict = { @CacheEvict(cacheNames = "customer", key = "#id"),
@CacheEvict(cacheNames = "customers", allEntries = true) })
@Override
public void delete(long id) {
this.customerRepository.deleteById(id);
}
@Cacheable(cacheNames = "customer", key = "#id", unless = "#result == null")
@Override
public Customer getCustomerById(long id) {
waitSomeTime();
return this.customerRepository.findById(id).orElse(null);
}
private void waitSomeTime() {
System.out.println("Long Wait Begin");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Long Wait End");
}
}
Dockerfile:
FROM openjdk:8
ADD ./target/spring-boot-redis-cache-0.0.1-SNAPSHOT.jar /usr/src/spring-boot-redis-cache-0.0.1-SNAPSHOT.jar
WORKDIR usr/src
ENTRYPOINT ["java","-jar", "spring-boot-redis-cache-0.0.1-SNAPSHOT.jar"]
Docker compose file:
docker-compose.yml
version: '3'
services:
db:
image: "postgres"
ports:
- "5432:5432"
environment:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ekoloji
cache:
image: "redis"
ports:
- "6379:6379"
environment:
- ALLOW_EMPTY_PASSWORD=yes
- REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL
app:
build: .
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://db/postgres
SPRING_DATASOURCE_USERNAME: postgres
SPRING_DATASOURCE_PASSWORD: ekoloji
SPRING_REDIS_HOST: cache
SPRING_REDIS_PORT: 6379
depends_on:
- db
- cache
- Build Java Jar.
$ mvn clean install
- Docker Compose Build and Run
$ docker-compose build --no-cache
$ docker-compose up --force-recreate
After running the application you can visit http://localhost:8080
.
You can see the endpoint in http://localhost:8080/swagger-ui.html
page.
I used Swagger for visualization endpoints.