diff --git a/pom.xml b/pom.xml
index ab3c73ff8a..f4606ec368 100644
--- a/pom.xml
+++ b/pom.xml
@@ -623,6 +623,7 @@
spring-boot-rest-2
spring-caching
+ spring-caching-2
spring-cloud
spring-cloud-bus
@@ -1079,6 +1080,7 @@
spring-boot-rest-2
spring-caching
+ spring-caching-2
spring-cloud
spring-cloud-bus
diff --git a/spring-caching-2/README.md b/spring-caching-2/README.md
new file mode 100644
index 0000000000..37095551a1
--- /dev/null
+++ b/spring-caching-2/README.md
@@ -0,0 +1 @@
+### Relevant articles:
diff --git a/spring-caching-2/pom.xml b/spring-caching-2/pom.xml
new file mode 100644
index 0000000000..6bb828e8bf
--- /dev/null
+++ b/spring-caching-2/pom.xml
@@ -0,0 +1,66 @@
+
+
+ 4.0.0
+ spring-caching-2
+ 0.1-SNAPSHOT
+ spring-caching-2
+ war
+
+
+ com.baeldung
+ parent-boot-2
+ 0.0.1-SNAPSHOT
+ ../parent-boot-2
+
+
+
+ 0.7.3
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.data
+ spring-data-commons
+
+
+ com.h2database
+ h2
+ runtime
+
+
+ org.projectlombok
+ lombok
+
+
+ org.springframework.boot
+ spring-boot-starter-cache
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ it.ozimov
+ embedded-redis
+ ${embedded.redis.version}
+
+
+ org.slf4j
+ slf4j-simple
+
+
+ test
+
+
+
diff --git a/spring-caching-2/src/main/java/com/baeldung/caching/redis/CacheConfig.java b/spring-caching-2/src/main/java/com/baeldung/caching/redis/CacheConfig.java
new file mode 100644
index 0000000000..89bdc2779d
--- /dev/null
+++ b/spring-caching-2/src/main/java/com/baeldung/caching/redis/CacheConfig.java
@@ -0,0 +1,33 @@
+package com.baeldung.caching.redis;
+
+import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+
+import java.time.Duration;
+
+import static org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair;
+
+@Configuration
+public class CacheConfig {
+
+ @Bean
+ public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {
+ return (builder) -> builder
+ .withCacheConfiguration("itemCache",
+ RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10)))
+ .withCacheConfiguration("customerCache",
+ RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(5)));
+ }
+
+ @Bean
+ public RedisCacheConfiguration cacheConfiguration() {
+ return RedisCacheConfiguration.defaultCacheConfig()
+ .entryTtl(Duration.ofMinutes(60))
+ .disableCachingNullValues()
+ .serializeValuesWith(SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
+ }
+
+}
diff --git a/spring-caching-2/src/main/java/com/baeldung/caching/redis/Item.java b/spring-caching-2/src/main/java/com/baeldung/caching/redis/Item.java
new file mode 100644
index 0000000000..d6115a4833
--- /dev/null
+++ b/spring-caching-2/src/main/java/com/baeldung/caching/redis/Item.java
@@ -0,0 +1,21 @@
+package com.baeldung.caching.redis;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import java.io.Serializable;
+
+@Data
+@Entity
+@AllArgsConstructor
+@NoArgsConstructor
+public class Item implements Serializable {
+
+ @Id
+ String id;
+
+ String description;
+}
diff --git a/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemController.java b/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemController.java
new file mode 100644
index 0000000000..63122c5938
--- /dev/null
+++ b/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemController.java
@@ -0,0 +1,19 @@
+package com.baeldung.caching.redis;
+
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@AllArgsConstructor
+public class ItemController {
+
+ private final ItemService itemService;
+
+ @GetMapping("/item/{id}")
+ public Item getItemById(@PathVariable String id) {
+ return itemService.getItemForId(id);
+ }
+
+}
diff --git a/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemRepository.java b/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemRepository.java
new file mode 100644
index 0000000000..d6222de621
--- /dev/null
+++ b/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemRepository.java
@@ -0,0 +1,6 @@
+package com.baeldung.caching.redis;
+
+import org.springframework.data.repository.CrudRepository;
+
+public interface ItemRepository extends CrudRepository- {
+}
diff --git a/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemService.java b/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemService.java
new file mode 100644
index 0000000000..6a59c7d74e
--- /dev/null
+++ b/spring-caching-2/src/main/java/com/baeldung/caching/redis/ItemService.java
@@ -0,0 +1,19 @@
+package com.baeldung.caching.redis;
+
+import lombok.AllArgsConstructor;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+
+@Service
+@AllArgsConstructor
+public class ItemService {
+
+ private final ItemRepository itemRepository;
+
+ @Cacheable(value = "itemCache")
+ public Item getItemForId(String id) {
+ return itemRepository.findById(id)
+ .orElseThrow(RuntimeException::new);
+ }
+
+}
diff --git a/spring-caching-2/src/main/java/com/baeldung/caching/redis/RedisCacheApplication.java b/spring-caching-2/src/main/java/com/baeldung/caching/redis/RedisCacheApplication.java
new file mode 100644
index 0000000000..3b337def01
--- /dev/null
+++ b/spring-caching-2/src/main/java/com/baeldung/caching/redis/RedisCacheApplication.java
@@ -0,0 +1,14 @@
+package com.baeldung.caching.redis;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+
+@SpringBootApplication
+@EnableCaching
+public class RedisCacheApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(RedisCacheApplication.class, args);
+ }
+}
diff --git a/spring-caching-2/src/main/resources/application.properties b/spring-caching-2/src/main/resources/application.properties
new file mode 100644
index 0000000000..080185b620
--- /dev/null
+++ b/spring-caching-2/src/main/resources/application.properties
@@ -0,0 +1,12 @@
+spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
+spring.datasource.driverClassName=org.h2.Driver
+spring.datasource.username=sa
+spring.datasource.password=
+
+# Enabling H2 Console
+spring.h2.console.enabled=true
+spring.h2.console.path=/h2
+
+# Connection details
+#spring.redis.host=localhost
+#spring.redis.port=6379
diff --git a/spring-caching-2/src/main/resources/data.sql b/spring-caching-2/src/main/resources/data.sql
new file mode 100644
index 0000000000..74e359b877
--- /dev/null
+++ b/spring-caching-2/src/main/resources/data.sql
@@ -0,0 +1 @@
+INSERT INTO ITEM VALUES('abc','ITEM1');
\ No newline at end of file
diff --git a/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java b/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java
new file mode 100644
index 0000000000..71a9729efd
--- /dev/null
+++ b/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java
@@ -0,0 +1,84 @@
+package com.baeldung.caching.redis;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
+import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration;
+import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import redis.embedded.RedisServer;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import java.util.Optional;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+@Import({ CacheConfig.class, ItemService.class })
+@ExtendWith(SpringExtension.class)
+@ImportAutoConfiguration(classes = { CacheAutoConfiguration.class, RedisAutoConfiguration.class })
+@EnableCaching
+class ItemServiceCachingIntegrationTest {
+
+ private static final String AN_ID = "id-1";
+ private static final String A_DESCRIPTION = "an item";
+
+ @MockBean
+ private ItemRepository mockItemRepository;
+
+ @Autowired
+ private ItemService itemService;
+
+ @Autowired
+ private CacheManager cacheManager;
+
+ @Test
+ void givenRedisCaching_whenFindItemById_thenItemReturnedFromCache() {
+ Item anItem = new Item(AN_ID, A_DESCRIPTION);
+ given(mockItemRepository.findById(AN_ID))
+ .willReturn(Optional.of(anItem));
+
+ Item itemCacheMiss = itemService.getItemForId(AN_ID);
+ Item itemCacheHit = itemService.getItemForId(AN_ID);
+
+ assertThat(itemCacheMiss).isEqualTo(anItem);
+ assertThat(itemCacheHit).isEqualTo(anItem);
+
+ verify(mockItemRepository, times(1)).findById(AN_ID);
+ assertThat(itemFromCache()).isEqualTo(anItem);
+ }
+
+ private Object itemFromCache() {
+ return cacheManager.getCache("itemCache").get(AN_ID).get();
+ }
+
+ @TestConfiguration
+ static class EmbeddedRedisConfiguration {
+
+ private final RedisServer redisServer;
+
+ public EmbeddedRedisConfiguration() {
+ this.redisServer = new RedisServer();
+ }
+
+ @PostConstruct
+ public void startRedis() {
+ redisServer.start();
+ }
+
+ @PreDestroy
+ public void stopRedis() {
+ this.redisServer.stop();
+ }
+ }
+
+}
diff --git a/spring-caching-2/src/test/resources/logback-test.xml b/spring-caching-2/src/test/resources/logback-test.xml
new file mode 100644
index 0000000000..215403c6a5
--- /dev/null
+++ b/spring-caching-2/src/test/resources/logback-test.xml
@@ -0,0 +1,5 @@
+
+
+
+
+