본문 바로가기
spring/spring batch

Spring Batch 5.0 마이그레이션

by moonsiri 2024. 5. 23.
728x90
반응형

Spring Batch 5.0은 2022년 11월 16일에 출시되었습니다.

 

주요 변경 사항

JDK 17 +

Spring Batch 4는 JDK 8 이상, Spring Framework 5.x를 지원했는데,

Spring Batch 5는 최소 버전으로 JDK 17, Spring 6을 기반으로합니다.

  • dependency 버전업그레이드
    • Spring Framework 6
    • Spring Integration 6
    • Spring Data 3
    • Spring AMQP 3
    • Spring for Apache Kafka 3
    • Micrometer 1.10
  • Java EE 기반의 API에서 Jakarta EE 9 이상을 기반으로 하여 패키지명이 javax 에서 jakarta로 변경되었습니다.
  • 기타
    • `org.springframework:spring-jdbc`는 이제 `spring-batch-core`의 필수 dependency입니다.
    • `junit:junit`은 더 이상 `spring-batch-test`에서 필수 dependency가 아닙니다.
    • `com.fasterxml.jackson.core:jackson-core`는 이제 `spring-batch-core`에서 선택 사항입니다.

 

 

Database 스키마 업데이트

Oracle

  • 새로운 애플리케이션을 위한 Oracle 시퀀스 순서가 정해졌습니다.
  • 기존 애플리케이션은 migration-oracle.sql 스크립트를 사용하여 시퀀스를 변경할 수 있습니다.
  • DDL 스크립트 이름 변경
    • `schema-drop-oracle10g.sql` → `schema-drop-oracle.sql`
    • `schema-oracle10g.sql` → `schema-oracle.sql`

 

MS SQLServer

v4까지는 테이블을 사용하여 시퀀스를 emulate했으나, 이제 실제 시퀀스를 사용합니다.

CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ START WITH 0 MINVALUE 0 MAXVALUE 9223372036854775807 NO CACHE NO CYCLE;
CREATE SEQUENCE BATCH_JOB_EXECUTION_SEQ START WITH 0 MINVALUE 0 MAXVALUE 9223372036854775807 NO CACHE NO CYCLE;
CREATE SEQUENCE BATCH_JOB_SEQ START WITH 0 MINVALUE 0 MAXVALUE 9223372036854775807 NO CACHE NO CYCLE;

기존 애플리케이션은 시퀀스 테이블의 마지막 값에서 시퀀스를 시작하도록 수정해야 합니다.

 

All platforms

`BATCH_JOB_EXECUTION` 테이블에서 `JOB_CONFIGURATION_LOCATION` 열이 제거되었습니다.

ALTER TABLE BATCH_JOB_EXECUTION DROP COLUMN JOB_CONFIGURATION_LOCATION;

 

다양한 Job 파라미터 타입 제공으로 `BATCH_JOB_EXECUTION_PARAMS` 테이블의 컬럼이 변경되었습니다.

CREATE TABLE BATCH_JOB_EXECUTION_PARAMS  (
	JOB_EXECUTION_ID BIGINT NOT NULL ,
---	TYPE_CD VARCHAR(6) NOT NULL ,
---	KEY_NAME VARCHAR(100) NOT NULL ,
---	STRING_VAL VARCHAR(250) ,
---	DATE_VAL DATETIME(6) DEFAULT NULL ,
---	LONG_VAL BIGINT ,
---	DOUBLE_VAL DOUBLE PRECISION ,
+++	PARAMETER_NAME VARCHAR(100) NOT NULL ,
+++	PARAMETER_TYPE VARCHAR(100) NOT NULL ,
+++	PARAMETER_VALUE VARCHAR(2500) ,
	IDENTIFYING CHAR(1) NOT NULL ,
	constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
	references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
);

마이그레이션 스크립트는 `org/springframework/batch/core/migration/5.0` 경로에 있습니다.

-- v4.3 → v5
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DATE_VAL;
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN LONG_VAL;
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DOUBLE_VAL;

ALTER TABLE BATCH_JOB_EXECUTION_PARAMS CHANGE COLUMN TYPE_CD PARAMETER_TYPE VARCHAR(100);
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS CHANGE COLUMN KEY_NAME PARAMETER_NAME VARCHAR(100);
ALTER TABLE BATCH_JOB_EXECUTION_PARAMS CHANGE COLUMN STRING_VAL PARAMETER_VALUE VARCHAR(2500);

v4까지는 4개의 타입(Long, Double, String, Date)만 지원했는데, v5부터는 모든 타입을 JobParameter로 사용할 수 있습니다.

---public class JobParameter implements Serializable {
+++public class JobParameter<T> implements Serializable {

---   private Object parameter;
+++   private T value;

---   private ParameterType parameterType;
+++   private Class<T> type;

}
// sample with v4
parameterName(parameterType)=parameterValue

// sample with v5
// DefaultJobParametersConverter
parameterName=parameterValue,parameterType,identificationFlag
// JsonJobParametersConverter
parameterName='{"value": "parameterValue", "type":"parameterType", "identifying": "booleanValue"}'




 

`BATCH_STEP_EXECUTION` 테이블에 `CREATE_TIME` 열이 추가되고, `START_TIME` 열의 NOT NULL 제약 조건이 제거되었습니다.

ALTER TABLE BATCH_STEP_EXECUTION ADD CREATE_TIME DATETIME(6) NOT NULL DEFAULT '1970-01-01 00:00:00' AFTER JOB_EXECUTION_ID;
ALTER TABLE BATCH_STEP_EXECUTION MODIFY START_TIME DATETIME(6) NULL;

 

Infrastructure beans configuration with @EnableBatchProcessing

Map 기반 Job Repository/Explorer 구현은 v4에서 더이상 사용되지 않으며 v5에서 완전히 제거되었고, 대신 JDBC 기반 구현을 사용해야 합니다.

v4.3까지 @EnableBatchProcessing 어노테이션이 TransactionManager Bean을 노출했으나, v5에서는 더 이상 노출되지 않습니다.

// Sample with v4
@Configuration
@EnableBatchProcessing
public class MyStepConfig {

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Bean
    public Step myStep() {
        return this.stepBuilderFactory.get("myStep")
                .tasklet(..) // or .chunk()
                .build();
    }

}
// Sample with v5
@Configuration
@EnableBatchProcessing
public class MyStepConfig {

    @Bean
    public Tasklet myTasklet() {
       return new MyTasklet();
    }

    @Bean
    public Step myStep(JobRepository jobRepository, Tasklet myTasklet, PlatformTransactionManager transactionManager) {
        return new StepBuilder("myStep", jobRepository)
                .tasklet(myTasklet, transactionManager) // or .chunk(chunkSize, transactionManager)
                .build();
    }

}

 

JobBuilderFactory와 StepBuilderFactory가 Deprecated 되었고, v5.2에서 제거될 예정입니다.

// Sample with v4
@Configuration
@EnableBatchProcessing
public class MyJobConfig {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Bean
    public Job myJob(Step step) {
        return this.jobBuilderFactory.get("myJob")
                .start(step)
                .build();
    }

}
// Sample with v5
@Configuration
@EnableBatchProcessing
public class MyJobConfig {

    @Bean
    public Job myJob(JobRepository jobRepository, Step step) {
        return new JobBuilder("myJob", jobRepository)
                .start(step)
                .build();
    }

}

 

DefaultBatchConfiguration

Spring Batch 5에서는 BatchConfigurer  DefaultBatchConfigurer가 제거되었고, 이를 대체하여  @EnableBatchProcessing 또는 DefaultBatchConfiguration을 사용해 설정을 관리합니다.

@EnableBatchProcessingJobRepository, StepScope 등의 Bean을 등록하고 처리하던 기능을 대신할 DefaultBatchConfiguration 클래스가 추가되었습니다.

// Sample with v4
@Configuration
public class BatchConfiguration extends DefaultBatchConfigurer {

	@Resource(name = BATCH_DATA_SOURCE_NM)
	private DataSource dataSource;

	@Resource(name = BATCH_TRANSACTION_NM)
	private PlatformTransactionManager platformTransactionManager;

	protected JobRepository createJobRepository() throws Exception {
		JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
		factory.setDataSource(dataSource);
		factory.setTransactionManager(platformTransactionManager);
		return factory.getObject();
	}
}
// sample with v5
@Configuration
public class BatchConfiguration extends DefaultBatchConfiguration {

	@Resource(name = BATCH_DATA_SOURCE_NM)
	private DataSource dataSource;

	@Resource(name = BATCH_TRANSACTION_NM)
	private PlatformTransactionManager platformTransactionManager;

	@Override
	protected DataSource getDataSource() {
		return dataSource;
	}

	@Override
	protected PlatformTransactionManager getTransactionManager() {
		return platformTransactionManager;
	}

getDataSource, getTransactionManager 등의 다양한 메소드를 제공하고 있습니다.

 

참고로 DefaultBatchConfiguration 사용하게되면 BatchAutoConfiguration이 활성화되지 않습니다.

@ConditionalOnMissingBean(value = DefaultBatchConfiguration.class, annotation = EnableBatchProcessing.class)
public class BatchAutoConfiguration {
/** 이하 생략 */

BatchAutoConfiguration 내부에서 정의해주는 JobLauncherApplicationRunner가 job.name으로 지정된 job 이름을 jobName으로 지정해주는 역할을 합니다. 그래서 DefaultBatchConfiguration을 사용할 경우 JobLauncherApplicationRunner을 Bean으로 등록해줘야 실행 argument로 --job.name을 설정할 수 있습니다.

@Configuration
@EnableConfigurationProperties(BatchProperties.class)
public class BatchConfiguration extends DefaultBatchConfiguration {

	@Bean
	@ConditionalOnMissingBean
	@ConditionalOnProperty(prefix = "spring.batch.job", name = "enabled", havingValue = "true", matchIfMissing = true)
	public JobLauncherApplicationRunner jobLauncherApplicationRunner(JobLauncher jobLauncher, JobExplorer jobExplorer,
		JobRepository jobRepository, BatchProperties properties) {
		JobLauncherApplicationRunner runner = new JobLauncherApplicationRunner(jobLauncher, jobExplorer, jobRepository);
		String jobName = properties.getJob().getName();
		if (StringUtils.hasText(jobName)) {
			if (Arrays.stream(BatchJobCd.values()).map(BatchJobCd::getJobName).noneMatch(jobName::equals)) {
				throw new IllegalArgumentException(jobName + "는 등록되지 않은 job name입니다. job name을 확인하세요.");
			}
			runner.setJobName(jobName);
		}
		return runner;
	}

 

추가로 `spring.batch.job.names`으로 여러 job을 설정하는 것에서 `spring.batch.job.name`으로 하나의 job만 실행하도록 변경되었습니다. 여러 job이 동시에 실행되는 것을 피하고 한 번에 하나의 job만 실행 할 수 있도록 명확히 하기 위함입니다.

spring:
  batch:
    job:
      name: ${job.name:NONE}

 

 

기타

Data type 변경

`org.springframework.batch.core.StepExecution` 및 `org.springframework.batch.core.StepContribution`의 메트릭 카운터가 int에서 long으로 변경되었습니다.

`JobExecution` 및 `StepExecution`의 시간 필드가 `java.util.Date`에서 `java.time.LocalDateTime`으로 변경되었습니다.

 

Observability 변경

Micrometer가 버전 1.10으로 업데이트되었습니다.

모든 태그가 미터 이름으로 접두어가 붙습니다.

 

Execution Context 직렬화 변경

기본 ExecutionContextSerializer가 Jackson에서 Base64로 변경되었습니다.

 

SystemCommandTasklet 변경

새로운 전략 인터페이스 `CommandRunner`가 도입되었고, 명령어 실행 방법이 개선되었습니다.

 

 

 

[Reference]

https://docs.spring.io/spring-batch/docs/4.3.x/reference/html/

https://docs.spring.io/spring-batch/docs/5.0.x/reference/html/

https://github.com/spring-projects/spring-batch/wiki/Spring-Batch-5.0-Migration-Guide

728x90
반응형

댓글