티스토리 뷰
개발 환경
- Spring Boot: 3.5.0
- Spring Batch: 5.2.2
- Java: 21
문제 상황
Spring Batch Job을 실행할 때 아래와 같은 JSON 문자열을 파라미터로 전달하고 싶었습니다.
{
"myType": "MY_TYPE_VALUE",
"myArray": [
{
"key": {"id": "001", "category": "MY_CATEGORY_VALUE"},
"param": {"foo": "002", "bar": "sampleValue"}
}
]
}
하지만 일반적인 방식으로 전달하면 다음과 같은 에러가 발생했습니다:
JobParametersConversionException: Unable to parse job parameter
왜 JSON 전달이 안 될까?
DefaultJobParametersConverter의 한계
Spring Batch의 DefaultJobParametersConverter는 다음과 같은 형식으로 파라미터를 파싱합니다:
paramKey=value,type
예를 들어:
count=100,long
name=test,string
문제는 JSON에도 , (쉼표)가 있다는 것입니다!
{"name":"test","age":30}
↑ 이 쉼표를 타입 구분자로 인식!
Spring Batch의 JsonJobParametersConverter (이거 안씀 주의)
Spring Batch 5.x부터 org.springframework.batch.core.converter.JsonJobParametersConverter가 제공됩니다.하지만 이것은 제가 원하는 방식과 차이가 있었는데:
Spring Batch JsonJobParametersConverter는 JobParameters 전체를 JSON으로 직렬화/역직렬화하는 용도입니다.
{
"paramName": {
"value": "actualValue",
"type": "java.lang.String",
"identifying": true
}
}
이를 위해서 기존 파라미터를 value, type을 명시하고, 다시 한번 이를 문자열 형식으로 escape 시켜야 하므로 파라미터 생김새가 지나치게 복잡한 문제가 있었습니다.
해결 방법: 커스텀 Converter
Json 형식의 파라미터를 구분하고 무조건 String 타입으로 처리하는, 즉 쉼표 파싱을 건너뛰는 커스텀 컨버터를 구현합니다.
예시 코드에서는 'JsonStr' 으로 끝나는 프로퍼티를 String 타입으로 판단하도록 했습니다.
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.converter.DefaultJobParametersConverter;
import org.springframework.stereotype.Component;
import java.util.Properties;
/**
* Json 형식 문자열 파라미터를 String으로 인식하기 위한 커스텀 JobParametersConverter
*
* DefaultJobParametersConverter 구현상 ',' 로 value와 type을 구분하는데
* JSON은 구조상 ','가 있어서 별도 처리가 필요함
*
* JsonStr로 끝나는 모든 프로퍼티는 자동으로 String으로 등록됩니다.
* 예: batchRequestJsonStr -> batchRequestJsonStr (String 타입)
*/
@Component
public class JsonStringAvailableJobParametersConverter extends DefaultJobParametersConverter {
private static final String JSON_STR_SUFFIX = "JsonStr";
@Override
public @NonNull JobParameters getJobParameters(@Nullable Properties properties) {
if (properties == null || properties.isEmpty()) {
return super.getJobParameters(properties);
}
// JsonStr로 끝나는 프로퍼티와 아닌 프로퍼티 분리
Properties jsonStrProperties = new Properties();
Properties otherProperties = new Properties();
for (String key : properties.stringPropertyNames()) {
if (key.endsWith(JSON_STR_SUFFIX)) {
jsonStrProperties.setProperty(key, properties.getProperty(key));
} else {
otherProperties.setProperty(key, properties.getProperty(key));
}
}
// 다른 Properties는 DefaultJobParametersConverter에 위임
JobParameters baseParams = super.getJobParameters(otherProperties);
// JsonStr로 끝나는 프로퍼티들을 String으로 추가
JobParametersBuilder builder = new JobParametersBuilder(baseParams);
for (String key : jsonStrProperties.stringPropertyNames()) {
String value = jsonStrProperties.getProperty(key);
builder.addString(key, value);
}
return builder.toJobParameters();
}
}
커스텀 Converter를 Bean으로 등록하고 사용처에서 아래와 같이 사용합니다.
@Value("#{jobParameters['batchRequestJsonStr']}")
배치 실행시 문자열 전송을 위해서 escape 처리는 필요합니다
--spring.batch.job.name=myBatchJob
batchRequestJsonStr={\"myType\":\"MY_TYPE_VALUE\",\"myArray\":[{\"key\":{\"id\":\"001\",\"category\":\"MY_CATEGORY_VALUE\"},\"param\":{\"foo\":\"002\",\"bar\":\"sampleValue\"}}]}
장점
- 복잡한 JSON 객체를 파라미터로 전달 가능
- 기존 파라미터 처리 방식은 그대로 유지
- 확장 가능: 여러 JSON 파라미터 추가 가능
- 명시적: 'JsonStr' 접미사로 의도 표현
'Spring Framework' 카테고리의 다른 글
| 스프링 부트에서 프로그램 실행 시 --가 붙는 argument와 붙지 않는 argument의 차이점 (0) | 2023.05.09 |
|---|---|
| Spring Boot에서 특정 필드 직렬화 방식 변경하기 (JsonSerializer, JsonDeserializer) (0) | 2023.05.01 |
| BeanFactory로 Bean생성시에 주의할점 (feat. InitializingBean) (0) | 2021.11.05 |
| 스프링 부트에서 CORS 문제 해결하기 (4) | 2019.10.19 |
| 스프링 부트로 GraphQL 시작하기 (5) | 2019.09.26 |