Codeit/프로젝트

[Monew] 트러블슈팅 - 뉴스 기사 백업

leejunkim 2025. 9. 16. 20:28

InvalidDefinitionException 오류

 

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (or disable `MapperFeature.REQUIRE_HANDLERS_FOR_JAVA8_TIMES`) (through reference chain: com.sprint.team2.monew.domain.article.entity.Article["createdAt"])

 

  @Bean
  @StepScope
  public JpaPagingItemReader<Article> newsBackupReader(
      EntityManagerFactory entityManagerFactory,
      @Value("#{jobParameters['backupDate']}") String backupDateStr
  ) {
    LocalDate backupDate = LocalDate.parse(backupDateStr);

    Map<String, Object> parameters = new HashMap<>();
    parameters.put("startDate", backupDate.atStartOfDay());
    parameters.put("endDate", backupDate.plusDays(1).atStartOfDay());

    return new JpaPagingItemReaderBuilder<Article>()
        .name("articleJpaPagingItemReader")
        .entityManagerFactory(entityManagerFactory)
        .queryString("SELECT a FROM Article a "
            + "WHERE a.createdAt >= :startDate AND a.createdAt < :endDate")
        .parameterValues(parameters)
        .pageSize(chunkSize)
        .build();
  }
  
  @Bean
  public ItemProcessor<Article, String> newsBackupProcessor() {
    // return article -> objectMapper.writeValueAsString(article)
    return objectMapper::writeValueAsString;
  }

 

InvalidDefinitionException (Java 8 날짜/시간 타입)

  • 기본 Jackson(ObjectMapper) 라이브러리가 Java 8의 날짜 타입(LocalDateTime)을 JSON으로 변환하는 방법을 몰라서 발생
  • 해결 방법: build.gradle에 jackson-datatype-jsr310 의존성을 추가하여 ObjectMapper가 LocalDateTime을 처리할 수 있도록 확장

build.gradle

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

 

이렇게 추가해주었더니... 이런 오류가 또 새로 떴다

 

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.sprint.team2.monew.domain.article.entity.Article["comments"]->org.hibernate.collection.spi.PersistentBag[0]->com.sprint.team2.monew.domain.comment.entity.Comment["user"]->com.sprint.team2.monew.domain.user.entity.User$HibernateProxy["hibernateLazyInitializer"])

 

InvalidDefinitionException (Hibernate 프록시 객체)

  • 오류 원인: JPA Entity를 JSON으로 직접 변환할 때, 지연 로딩으로 설정된 다른 Entity(e.g., Article -> Comment -> User)가 실제 객체가 아닌 하이버네이트의 프록시(가짜) 객체 상태였음. ObjectMapper는 이 프록시 객체를 어떻게 처리해야 할지 몰라서 발생.

해결 방법:

1. build.gradle에 추가

build.gradle에 jackson-datatype-hibernate6 의존성을 추가하여 ObjectMapper가 하이버네이트 프록시 객체를 이해하도록 함.

implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate6'

 

 

2. BackupBatchConfig.java에서 new ObjectMapper()로 직접 생성하던 코드를 삭제하고, 스프링이 자동으로 구성해주는 ObjectMapper를 의존성 주입(@RequiredArgsConstructor와 final 키워드)으로 받도록 수정

 

3. 새로운 파일 생성:

  • 스프링이 이 모듈을 확실하게 인식하고 ObjectMapper에 등록하도록 별도의 설정 파일(JsonConfiguration.java)을 만들고, Hibernate6Module을 @Bean으로 직접 등록함
package com.sprint.team2.monew.global.config;

import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.datatype.hibernate6.Hibernate6Module;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JsonConfiguration {

  @Bean
  public Module hibernateModule() {
    return new Hibernate6Module();
  }
}

 

그랬더니 s3에 잘 업로드가 된 듯하다.