diff --git a/compose.yaml b/compose.yaml
index 972b861..88a960c 100644
--- a/compose.yaml
+++ b/compose.yaml
@@ -10,5 +10,14 @@ services:
volumes:
- postgres_data:/var/lib/postgresql/data # Persists database data
+ redis:
+ image: redis:7-alpine
+ ports:
+ - '6379:6379'
+ volumes:
+ - redis_data:/data
+ command: redis-server --appendonly yes
+
volumes:
- postgres_data:
\ No newline at end of file
+ postgres_data:
+ redis_data:
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 59fe667..8ec1cd8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -155,20 +155,31 @@
cloudinary-http5
2.3.0
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-hibernate6
+
org.flywaydb
flyway-core
10.10.0
+
org.flywaydb
flyway-database-postgresql
10.10.0
-
+
-
+
diff --git a/src/main/java/ua/com/javarush/gnew/contactm/ContactManagerSpringBootApplication.java b/src/main/java/ua/com/javarush/gnew/contactm/ContactManagerSpringBootApplication.java
index 85d1e7e..8920d0b 100644
--- a/src/main/java/ua/com/javarush/gnew/contactm/ContactManagerSpringBootApplication.java
+++ b/src/main/java/ua/com/javarush/gnew/contactm/ContactManagerSpringBootApplication.java
@@ -2,8 +2,10 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
+@EnableCaching
public class ContactManagerSpringBootApplication {
public static void main(String[] args) {
diff --git a/src/main/java/ua/com/javarush/gnew/contactm/DTOs/ContactCacheDto.java b/src/main/java/ua/com/javarush/gnew/contactm/DTOs/ContactCacheDto.java
new file mode 100644
index 0000000..7d75ac0
--- /dev/null
+++ b/src/main/java/ua/com/javarush/gnew/contactm/DTOs/ContactCacheDto.java
@@ -0,0 +1,25 @@
+package ua.com.javarush.gnew.contactm.DTOs;
+
+import java.util.Date;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class ContactCacheDto {
+ private long id;
+ private String name;
+ private String lastName;
+ private String imageUrl;
+ private Date createDate;
+ private Date modifyDate;
+ private List emailAddresses;
+ private List phoneNumbers;
+ private List socialNetworks;
+ private String contactBookName;
+}
diff --git a/src/main/java/ua/com/javarush/gnew/contactm/component/RedisHealthCheck.java b/src/main/java/ua/com/javarush/gnew/contactm/component/RedisHealthCheck.java
new file mode 100644
index 0000000..a90de18
--- /dev/null
+++ b/src/main/java/ua/com/javarush/gnew/contactm/component/RedisHealthCheck.java
@@ -0,0 +1,26 @@
+package ua.com.javarush.gnew.contactm.component;
+
+import jakarta.annotation.PostConstruct;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+@Slf4j
+public class RedisHealthCheck {
+
+ private final RedisTemplate redisTemplate;
+
+ @PostConstruct
+ public void checkRedisConnection() {
+ try {
+ String pong = redisTemplate.getConnectionFactory().getConnection().ping();
+ log.info("Redis connection successful. Response: {}", pong);
+ } catch (Exception e) {
+ log.warn("Redis connection failed: {}", e.getMessage());
+ log.warn("Application will continue without Redis caching");
+ }
+ }
+}
diff --git a/src/main/java/ua/com/javarush/gnew/contactm/config/RedisConfig.java b/src/main/java/ua/com/javarush/gnew/contactm/config/RedisConfig.java
new file mode 100644
index 0000000..9440538
--- /dev/null
+++ b/src/main/java/ua/com/javarush/gnew/contactm/config/RedisConfig.java
@@ -0,0 +1,74 @@
+package ua.com.javarush.gnew.contactm.config;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.hibernate6.Hibernate6Module;
+import java.time.Duration;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+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.core.RedisTemplate;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.RedisSerializationContext;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+@Slf4j
+@Configuration
+@RequiredArgsConstructor
+public class RedisConfig {
+
+ /** Shared ObjectMapper with Hibernate support. */
+ @Bean
+ public ObjectMapper redisObjectMapper() {
+ Hibernate6Module hibernateModule = new Hibernate6Module();
+ hibernateModule.configure(Hibernate6Module.Feature.FORCE_LAZY_LOADING, false);
+ hibernateModule.configure(
+ Hibernate6Module.Feature.SERIALIZE_IDENTIFIER_FOR_LAZY_NOT_LOADED_OBJECTS, true);
+
+ return new ObjectMapper().registerModule(hibernateModule);
+ }
+
+ /** Generic JSON serializer using the shared ObjectMapper. */
+ @Bean
+ public RedisSerializer