문제 상황
에러 로그
Caused by: java.lang.IllegalArgumentException: The class with java.util.ImmutableCollections$ListN and name of java.util.ImmutableCollections$ListN is not trusted.
If you believe this class is safe to deserialize, you can add it to the base set of trusted classes at construction time or provide an explicit mapping using Jackson annotations or a custom ObjectMapper.
If the serialization is only done by a trusted source, you can also enable default typing.
at org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer$TrustedTypeIdResolver.typeFromId(Jackson2ExecutionContextStringSerializer.java:353) ~[spring-batch-core-4.3.8.jar!/:4.3.8]
해당 오류는 Spring Batch의 ExecutionContext에서 발생하는 오류
구체적으론 Jackson2 ExecutionContext Serializer에 의해 발생하는 거 같다. 이 오류는 특정 클래스 또는 라이브러리가 직렬화 및 역직렬화 중에 문제를 발생시키는 경우에 발생할 수 있다고 한다.
Spring Batch는 기본적으로 Jackson을 사용하여 ExecutionContext를 직렬화한다.
원인
오류를 보고 한 가지 걸리는 점이 있었다. 필자는 Java 8 LocalDateTime 직렬화 역 직렬화 오류를 방지하기 위해 직접 ObjectMapper를 Bean으로 등록했었다. 또한 ExecutionContextSerializer를 따로 Configuration 해주지 않았다. 그러하여 Default로 생성되는 ExecutionContextSerializer를 쓰고 있기 때문에 객체의 직렬화 중 오류가 발생하는 결론에 다다랐다.
해결
Spring Batch 컴포넌트 ExecutionContextSerializer을 직접 등록해 줌으로써 해결하였다.
추가로 데이터베이스와 실행 컨텍스트 데이터의 직렬화 및 역직렬화와 관련된 설정도 해주었다.
@Configuration
@RequiredArgsConstructor
public class BatchConfig {
private final ObjectMapper objectMapper; //ObjectMapper 주입받기
@Bean
public ExecutionContextSerializer customSerializer() { //ExecutionContext을 직렬화/역직렬화 하기 위한 Serializer 등록
Jackson2ExecutionContextStringSerializer defaultSerializer = new Jackson2ExecutionContextStringSerializer(AttendanceJobDto.class.getName());
defaultSerializer.setObjectMapper(objectMapper); //ExecutionContextSerializer에 ObjectMapper 주입
return defaultSerializer;
}
@Bean
public BatchConfigurer myBatchConfigurer(DataSource dataSource, //DB연결에 대한 정보를 담은 DataSource
ExecutionContextSerializer executionContextSerializer, //위에서 Bean으로 등록한 ExecutionContextSerializer
PlatformTransactionManager transactionManager) { //트랜잭션을 관리하는 PlatformTransactionManager
return new DefaultBatchConfigurer(dataSource) {
@Override
protected JobExplorer createJobExplorer() throws Exception { //작업 탐색기 등록
JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean();
jobExplorerFactoryBean.setDataSource(dataSource); //DataSource 주입
jobExplorerFactoryBean
.setSerializer(executionContextSerializer); //ExecutionContextSerializer 주입
jobExplorerFactoryBean.afterPropertiesSet();
return jobExplorerFactoryBean.getObject();
}
@Override
protected JobRepository createJobRepository() throws Exception { //작업 저장소 등록
JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
jobRepositoryFactoryBean.setDataSource(dataSource); //DataSource 주입
jobRepositoryFactoryBean
.setSerializer(executionContextSerializer); //ExecutionContextSerializer 주입
jobRepositoryFactoryBean.setTransactionManager(transactionManager); //PlatformTransactionManager 주입
jobRepositoryFactoryBean.afterPropertiesSet();
return jobRepositoryFactoryBean.getObject();
}
};
}
}
참고 자료
'Spring' 카테고리의 다른 글
[Spring] WebClient 적용기 (2) | 2023.02.27 |
---|---|
[Spring] 비동기 처리(Controller) With @Callable (1) | 2023.02.23 |
[Spring] Multipartfile, Json 동시에 전송하는 방법 2가지 (3) | 2022.09.11 |
[Spring] Junit4, Junit5 Test코드의 차이(Trouble Shooting) (1) | 2022.06.17 |
[Spring] Spring Boot 기본 MVC Pattern (0) | 2022.05.23 |