diff --git a/build.gradle.kts b/build.gradle.kts index 90f0258..d7b6f12 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -44,7 +44,6 @@ dependencies { implementation(libs.spring.boot.starter.validation) implementation(libs.spring.boot.starter.redis) implementation(libs.spring.boot.starter.cache) - implementation(libs.spring.boot.starter.security) implementation(libs.spring.boot.starter.jpa) implementation(libs.mybatis.starter.core) implementation(libs.flyway.core) @@ -52,9 +51,7 @@ dependencies { implementation(libs.jackson.jsr310) testImplementation(libs.spring.boot.starter.test) testImplementation(libs.reactor.test) - testImplementation(libs.spring.security.test) testImplementation(libs.mybatis.starter.test) - // runtimeOnly(libs.postgres.driver) runtimeOnly(libs.mysql.driver) testRuntimeOnly(libs.h2.database) testRuntimeOnly(libs.junit.launcher) diff --git a/src/main/java/com/onixbyte/deltaforceguide/config/CacheConfig.java b/src/main/java/com/onixbyte/deltaforceguide/config/CacheConfig.java new file mode 100644 index 0000000..0502c4a --- /dev/null +++ b/src/main/java/com/onixbyte/deltaforceguide/config/CacheConfig.java @@ -0,0 +1,102 @@ +package com.onixbyte.deltaforceguide.config; + +import com.onixbyte.deltaforceguide.shared.JacksonRedisSerialiser; +import org.springframework.cache.annotation.EnableCaching; +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 java.time.Duration; + +/** + * Configuration class for Redis-based caching components. + *
+ * This configuration class provides beans for Redis cache management and template operations + * within the Helix application. It configures custom serialisation strategies using + * {@link GenericJackson2JsonRedisSerializer} for values and string serialisation for keys, + * ensuring optimal performance and compatibility with JSON-based data structures. + *
+ * The configuration includes: + *
+ * This method configures a {@link RedisCacheManager} that uses string serialisation for cache + * keys and {@link GenericJackson2JsonRedisSerializer} for cache values. This setup ensures that + * complex objects can be stored and retrieved from Redis cache whilst maintaining readability + * and compatibility with JSON-based systems. + * + * @param connectionFactory the Redis connection factory used to establish connections + * @return a configured {@link RedisCacheManager} with custom serialisation settings + * @see RedisCacheManager + * @see GenericJackson2JsonRedisSerializer + * @see RedisSerializationContext + */ + @Bean + public RedisCacheManager cacheManager( + RedisConnectionFactory connectionFactory + ) { + var _keySerializer = RedisSerializer.string(); + + var cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() + .serializeKeysWith(RedisSerializationContext.SerializationPair + .fromSerializer(_keySerializer)) + .serializeValuesWith(RedisSerializationContext.SerializationPair + .fromSerializer(JacksonRedisSerialiser.INSTANCE)) + .entryTtl(Duration.ofMinutes(90L)); + + return RedisCacheManager.RedisCacheManagerBuilder + .fromConnectionFactory(connectionFactory) + .cacheDefaults(cacheConfiguration) + .build(); + } + + /** + * Creates a Redis template for direct Redis operations with custom serialisation. + *
+ * This method configures a {@link RedisTemplate} that uses string serialisation for keys + * and {@link GenericJackson2JsonRedisSerializer} for values. This template provides low-level + * access to Redis operations whilst ensuring consistent serialisation strategies across + * the application. + *
+ * The template is fully configured and ready for use after bean creation.
+ *
+ * @param connectionFactory the Redis connection factory used to establish connections
+ * @return a fully configured {@link RedisTemplate} for Redis operations
+ * @see RedisTemplate
+ * @see GenericJackson2JsonRedisSerializer
+ * @see RedisSerializer
+ */
+ @Bean
+ public RedisTemplate
+ * Example: "{@code 2023-10-27 15:30:45}"
+ */
+ public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+ /**
+ * A {@link DateTimeFormatter} for formatting and parsing dates only, using the
+ * pattern "yyyy-MM-dd".
+ *
+ * Example: "{@code 2023-10-27}"
+ */
+ public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+ /**
+ * A {@link DateTimeFormatter} for formatting and parsing times only, using the
+ * pattern "HH:mm:ss".
+ *
+ * Example: "{@code 15:30:45}"
+ */
+ public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
+
+ /**
+ * A {@link DateTimeFormatter} for formatting and parsing year and month only, using the
+ * pattern "yyyy-MM".
+ *
+ * Example: "{@code 2023-10}"
+ */
+ public static final DateTimeFormatter YEAR_MONTH_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM");
+}
+
diff --git a/src/main/java/com/onixbyte/deltaforceguide/shared/JacksonModules.java b/src/main/java/com/onixbyte/deltaforceguide/shared/JacksonModules.java
new file mode 100644
index 0000000..36332aa
--- /dev/null
+++ b/src/main/java/com/onixbyte/deltaforceguide/shared/JacksonModules.java
@@ -0,0 +1,34 @@
+package com.onixbyte.deltaforceguide.shared;
+
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+
+public class JacksonModules {
+
+ public static final SimpleModule DATE_TIME_MODULE = initialiseDateTimeModule();
+
+ private static SimpleModule initialiseDateTimeModule() {
+ var javaTimeModule = new JavaTimeModule();
+ javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatters.DATE_TIME_FORMATTER));
+ javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatters.DATE_TIME_FORMATTER));
+
+ javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatters.DATE_FORMATTER));
+ javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatters.DATE_FORMATTER));
+
+ javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatters.TIME_FORMATTER));
+ javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatters.TIME_FORMATTER));
+
+ return javaTimeModule;
+ }
+}
+
diff --git a/src/main/java/com/onixbyte/deltaforceguide/shared/JacksonRedisSerialiser.java b/src/main/java/com/onixbyte/deltaforceguide/shared/JacksonRedisSerialiser.java
new file mode 100644
index 0000000..5a300ba
--- /dev/null
+++ b/src/main/java/com/onixbyte/deltaforceguide/shared/JacksonRedisSerialiser.java
@@ -0,0 +1,22 @@
+package com.onixbyte.deltaforceguide.shared;
+
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
+
+public class JacksonRedisSerialiser {
+
+ public static final GenericJackson2JsonRedisSerializer INSTANCE = initialiseSerializer();
+
+ private static GenericJackson2JsonRedisSerializer initialiseSerializer() {
+ var serializer = new GenericJackson2JsonRedisSerializer();
+
+ serializer.configure((configurer) -> {
+ configurer.registerModule(new JavaTimeModule());
+ configurer.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+ });
+
+ return serializer;
+ }
+}
+