Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type
java.time.LocalDateTimenot supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: com.tdd.ecommerce.product.domain.entity.Product["regDate"])
Redis Cache를 적용하려고 했더니 해당 오류가 발생했다.
@Cacheable(value = "getProductInfo"
, key = "#productId"
, unless = "#productId == null")
public Product getProductById(Long productId) {
Product product = productRepository.findByProductId(productId);
if(product == null)
throw new BusinessException(ECommerceExceptions.INVALID_PRODUCT);
return product;
}
LocalDateTime 타입이 Jackson에서 기본적으로 지원되지 않아 발생하는 문제.
Spring Data Redis에서 LocalDateTime을 직렬화하려면 jackson-datatype-jsr310 모듈을 추가하여 Jackson이 Java 8의 날짜와 시간 타입을 지원할 수 있도록 설정해야 한다.
jackson-datatype-jsr310 라이브러리 추가<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.15.2</version> <!-- 최신 버전 사용 -->
</dependency>
xml
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2' // 최신 버전 사용
gradle
이거만 추가하면 되는게 아니라,
LocalDateTime을 쓰는 regDate, editDate 부분에 직렬화, 역직렬화 코드를 추가해 주어야 한다.
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class TimeStamped {
@CreatedDate
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonFormat(pattern ="yyyy-MM-dd kk:mm:ss")
@Column(updatable = false, nullable = false)
private LocalDateTime regDate;
@LastModifiedDate
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonFormat(pattern ="yyyy-MM-dd kk:mm:ss")
@Column(nullable = true)
private LocalDateTime editDate;
}
ObjectMapper 설정import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
return mapper;
}
}
RedisTemplate 설정Jackson2JsonRedisSerializer에 등록한 ObjectMapper를 전달하여 LocalDateTime 타입을 직렬화할 수 있도록 한다.import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
serializer.setObjectMapper(mapper);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
return template;
}
}
ObjectMapper는 Java에서 JSON을 다루는 데 사용되는 Jackson 라이브러리의 주요 클래스.
주로 JSON과 Java 객체 간의 변환(즉, 직렬화 및 역직렬화)을 담당한다.