[에러 해결] JAVA 8 LocalDateTime 직렬화/역직렬화 문제 해결

이재훈·2023년 5월 10일
1

삽질모음집

목록 보기
1/8

Spring boot에서 RabbitMQ로 데이터를 보내는 도중 에러가 발생하였습니다.

해석하자면 java.time.LocalDateTime을 직렬화 하려면 com.fasterxml.jackson.datatype:jackson-datatype-jsr310 디펜던시를 추가해라 ~ 라는 내용입니다.

문제가 발생한 코드입니다. rabbitTemplate는 내부적으로 Object를 매개변수로 받고 ObjectMapper로 직렬화를 하여 메시지를 전송합니다.

이 직렬화 하는 과정에서 LocalDateTime을 직렬화를 지원하지 않으니 exception이 발생합니다.

dependencies {
	implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
	implementation 'com.fasterxml.jackson.core:jackson-databind'
}    

필요한 디펜던시를 추가해 주었습니다.

com.fasterxml.jackson.core:jackson-databind

JSON 구조 데이터에 대한 데이터 바인딩을 JAVA 객체에 제공하는 핵심 라이브러리 입니다. JSON data -> Java Object , Java Object -> JSON data 로 직렬화 역직렬화를 가능하게 합니다.

com.fasterxml.jackson.datatype:jackson-datatype-jsr310

Jackson에서 Java8 날짜/시간 API를 지원하는 확장 라이브러리입니다. LocalDateTime, LocalDate, ZonedDateTIme 등과 같은 Java8 날짜/시간 개체를 JSON data로 직렬화 및 역직렬화할 수 있습니다.

추가 후 LocalDateTime을 사용하는 클래스에 추가로 코드를 작성해줍니다.

public class InitMessage {
	// ...코드 생략

    @JsonProperty("startDateTime")
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
    private LocalDateTime startDateTime;

    @JsonProperty("endDateTime")
    @JsonSerialize(using = LocalDateTimeSerializer.class) // 직렬화 시 필요
    @JsonDeserialize(using = LocalDateTimeDeserializer.class) // 역직렬화 시 필요
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
    private LocalDateTime endDateTime;

}

이제 ObjectMapper에 직접 모듈을 추가해주도록 하겠습니다. 저는 스프링 부트를 사용하고 있고 생성자 DI를 사용하여 ObjectMapper를 초기화 하도록 하겠습니다.

주석 달린 쪽을 보시면 이해가 되실 겁니다.

@Component
@Slf4j
public class DevReg implements CommandLineRunner {

    private final RabbitTemplate rabbitTemplate;
    private final ObjectMapper objectMapper;

    private final String MSG_EXCHANGE = "exchange.message";
    private final String MSG_ROUTING_KEY = "message";

    public DevReg(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
        this.objectMapper = new ObjectMapper();
        this.objectMapper.registerModule(new Jdk8Module()); // Jdk8Module 추가
        this.objectMapper.registerModule(new JavaTimeModule()); // JavaTimeModule 추가
        this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        this.objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
    }

    @Override
    public void run(String... args) throws Exception {

        MessageInfo messageInfo = InitMessage
                                    .builder()
                                    // 생략
                                    .startDateTime(LocalDateTime.now())
                                    .endDateTime(LocalDateTime.now())
                                    .build();

        rabbitTemplate.convertAndSend(MSG_EXCHANGE, MSG_ROUTING_KEY, messageInfo);

    }
}

이렇게 수정 후 다시 메시지를 보내게 되면 exception이 사라지고 데이터가 잘 전송됩니다.

profile
부족함을 인정하고 노력하자

0개의 댓글