dataSource
오버라이드 예// 다른 configuration class 에서 DataSource 생성 - embedded 예제 @Bean public DataSource batchDataSource() { return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2) .addScript("classpath:/org/springframework/batch/core/schema-h2.sql") .build(); } @EnableBatchProcessing @Configuration public class BatchApplication extends DefaultBatchConfigurer { // dataSource 설정부분 override. transactionManager도 자동으로 생성함. @Autowired @Override public void setDataSource(@Qualifier("batchDataSource") DataSource batchDataSource) { super.setDataSource(batchDataSource); } }
dataSource
자체를 null로 지정하면 MapJobRepository
로 DB없이 작동하게 만들어진다.DefaultBatchConfigurer
사용시 TransactionManager 오작동 문제가 발생한다. SpringBoot와 SpringBatch 참고org.springframework.batch.core.repository.support.JobRepositoryFactoryBean
로 SimpleJobRepository
생성MapJobRepositoryFactoryBean
로 in memory Job Repository 생성 가능.org.springframework.batch.core
패키지에 schema-*.sql
파일이 Batch Job Repository DB 스키마이다.schema-mysql.sql
의 경우 TransactionManager를 지정하지 않으면 다음과 같은 오류가 발생한다.
java.lang.IllegalStateException: To use the default BatchConfigurer the context must contain precisely one DataSource, found X
TransactionManager 를 ResourcelessTransactionManager 로 지정하면 된다.
혹은 아래와 같이 propagation=“NEVER”
로 지정한다.
<batch:job id="jobid"> <batch:step id="step1"> <batch:tasklet ref="taskletId" transaction-manager="transactionManager"> <batch:transaction-attributes propagation="NEVER"/> </batch:tasklet> </batch:step> </batch:job>
@Value(“#{jobParameter[paramName]}” String param
형태로 Job Parameter를 받을 수 있다.@Bean @JobScope public Step myStep(@Value("#{jobParameters[date]}" String date, @Value("#{jobParameters[count]}") long count) { // ... }
ResourcelessTransactionManager
를 사용하거나 CHUNK 를 작게 가져가야 한다.ResourcelessTransactionManager
로 Batch Job 을 지정하면, Batch job 의 chunk 가 아닌, 각각의 Service
/Repository
등의 메소드에 설정된 @Transactional
을 기준으로 트랜잭션이 작동하게 된다.RunIdIncrementer
의 특정 파라미터(run.id
) 값을 계속 증가시켜준다.jobBuilderFactory.get("myJobName") .start(step()) . ..... .incrementer(new RunIdIncrementer()) .build();
RunIdIncrementer
를 사용하게 되면 기존 job이 실패했을 경우 기존 실패 Job의 파라미터가 현재 파라미터를 덮어쓰는 현상이 발생한다.RunIdIncrementer
가 동일 파라미터로 Job을 실행하려고 사용하는 것이라서 인 듯 하다.RunIdIncrementer
를 사용하면서도 파라미터 값을 유지하려면 다른 방식을 써야 한다./** * 파라미터를 복사하지 않는 RunIdIncrementer */ public class ParamCleanRunIdIncrementer implements JobParametersIncrementer { private static String RUN_ID_KEY = "run.id"; private String key = RUN_ID_KEY; public void setKey(String key) { this.key = key; } @Override public JobParameters getNext(JobParameters parameters) { JobParameters params = (parameters == null) ? new JobParameters() : parameters; long id = params.getLong(key, 0L) + 1; return new JobParametersBuilder().addLong(key, id).toJobParameters(); // 이부분이 RunIdIncrementer와 다르다. } }
@StepScope
등을 사용하는 등 할 경우 리턴 타입을 ItemReader<X>
, ItemWriter<Y>
처럼 인터페이스로 할 경우 프록시 객체가 생성되고 그로 인해서 instanceOf
를 사용하는 일부 코드들이 작동하지 않거나, annotation 기반의 listener 등이 동작하지 않는 문제를 일으킨다.o.s.b.c.l.AbstractListenerFactoryBean : org.springframework.batch.item.ItemReader is an interface. The implementing class will not be queried for annotation based listener configurations. If using @StepScope on a @Bean method, be sure to return the implementing class so listner annotations can be used.
org.springframework.batch.item.ItemReader는 인터페이스입니다. 구현 클래스는 어노테이션 기반 listener 구성에 대해 실행되지 않습니다. @Bean 메소드에서 @StepScope를 사용하는 경우 listner 어노테이션을 사용할 수 있도록 구현 클래스를 리턴해야합니다.
setJob()
으로 특정 Job을 지정하거나, 그냥 @Autowired
될 수도 있음.@MockBean
도 가능.