[SPRING] Spring 배치는 태스크 릿에서 동적으로 생성 된 단계를 실행합니다.
SPRINGSpring 배치는 태스크 릿에서 동적으로 생성 된 단계를 실행합니다.
나는 다음을하는 봄 배치 일을 가지고있다.
1 단계. 처리해야 할 개체 목록을 만듭니다.
2 단계. 1 단계에서 작성된 오브젝트 목록에있는 항목 수에 따라 단계 목록을 작성하십시오.
3 단계 : 2 단계에서 작성한 단계 목록에서 단계를 실행합니다.
실행중인 x 단계는 executeDynamicStepsTasklet ()에서 아래에 수행됩니다. 코드가 오류없이 실행되는 동안 아무 것도하지 않는 것처럼 보입니다. 나는 그 방법에서 뭘 올바르게 보이는지?
감사
/* * */
@Configuration
public class ExportMasterListCsvJobConfig {
public static final String JOB_NAME = "exportMasterListCsv";
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Value("${exportMasterListCsv.generateMasterListRows.chunkSize}")
public int chunkSize;
@Value("${exportMasterListCsv.generateMasterListRows.masterListSql}")
public String masterListSql;
@Autowired
public DataSource onlineStagingDb;
@Value("${out.dir}")
public String outDir;
@Value("${exportMasterListCsv.generatePromoStartDateEndDateGroupings.promoStartDateEndDateSql}")
private String promoStartDateEndDateSql;
private List<DivisionIdPromoCompStartDtEndDtGrouping> divisionIdPromoCompStartDtEndDtGrouping;
private List<Step> dynamicSteps = Collections.synchronizedList(new ArrayList<Step>()) ;
@Bean
public Job exportMasterListCsvJob(
@Qualifier("createJobDatesStep") Step createJobDatesStep,
@Qualifier("createDynamicStepsStep") Step createDynamicStepsStep,
@Qualifier("executeDynamicStepsStep") Step executeDynamicStepsStep) {
return jobBuilderFactory.get(JOB_NAME)
.flow(createJobDatesStep)
.next(createDynamicStepsStep)
.next(executeDynamicStepsStep)
.end().build();
}
@Bean
public Step executeDynamicStepsStep(
@Qualifier("executeDynamicStepsTasklet") Tasklet executeDynamicStepsTasklet) {
return stepBuilderFactory
.get("executeDynamicStepsStep")
.tasklet(executeDynamicStepsTasklet)
.build();
}
@Bean
public Tasklet executeDynamicStepsTasklet() {
return new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
FlowStep flowStep = new FlowStep(createParallelFlow());
SimpleJobBuilder jobBuilder = jobBuilderFactory.get("myNewJob").start(flowStep);
return RepeatStatus.FINISHED;
}
};
}
public Flow createParallelFlow() {
SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
taskExecutor.setConcurrencyLimit(1);
List<Flow> flows = dynamicSteps.stream()
.map(step -> new FlowBuilder<Flow>("flow_" + step.getName()).start(step).build())
.collect(Collectors.toList());
return new FlowBuilder<SimpleFlow>("parallelStepsFlow")
.split(taskExecutor)
.add(flows.toArray(new Flow[flows.size()]))
.build();
}
@Bean
public Step createDynamicStepsStep(
@Qualifier("createDynamicStepsTasklet") Tasklet createDynamicStepsTasklet) {
return stepBuilderFactory
.get("createDynamicStepsStep")
.tasklet(createDynamicStepsTasklet)
.build();
}
@Bean
@JobScope
public Tasklet createDynamicStepsTasklet() {
return new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
for (DivisionIdPromoCompStartDtEndDtGrouping grp: divisionIdPromoCompStartDtEndDtGrouping){
System.err.println("grp: " + grp);
String stepName = "stp_" + grp;
String fileName = grp + FlatFileConstants.EXTENSION_CSV;
Step dynamicStep =
stepBuilderFactory.get(stepName)
.<MasterList,MasterList> chunk(10)
.reader(queryStagingDbReader(
grp.getDivisionId(),
grp.getRpmPromoCompDetailStartDate(),
grp.getRpmPromoCompDetailEndDate()))
.writer(masterListFileWriter(fileName))
.build();
dynamicSteps.add(dynamicStep);
}
System.err.println("createDynamicStepsTasklet dynamicSteps: " + dynamicSteps);
return RepeatStatus.FINISHED;
}
};
}
public FlatFileItemWriter<MasterList> masterListFileWriter(String fileName) {
FlatFileItemWriter<MasterList> writer = new FlatFileItemWriter<>();
writer.setResource(new FileSystemResource(new File(outDir, fileName )));
writer.setHeaderCallback(masterListFlatFileHeaderCallback());
writer.setLineAggregator(masterListFormatterLineAggregator());
return writer;
}
이제는 실행해야 할 동적 단계 목록이 있으며 StepScope에 있다고 생각합니다. 누군가가 그걸 어떻게 실행하는지 조언 해 줄 수 있어요?
해결법
-
==============================
1.이것은 작동하지 않습니다. Tasklet은 FlowStep이있는 작업을 첫 번째 단계로 만듭니다. jobBuilderfactory를 사용하면 작업이 생성됩니다. 그것을 시작하지 않습니다. methodname "start"는 첫 번째 단계 만 정의하므로 오해의 소지가 있습니다. 그러나 그것은 일을 시작하지 않습니다.
이것은 작동하지 않습니다. Tasklet은 FlowStep이있는 작업을 첫 번째 단계로 만듭니다. jobBuilderfactory를 사용하면 작업이 생성됩니다. 그것을 시작하지 않습니다. methodname "start"는 첫 번째 단계 만 정의하므로 오해의 소지가 있습니다. 그러나 그것은 일을 시작하지 않습니다.
일단 작업이 시작되면 작업 (해당 단계 및 하위 단계)의 구조를 변경할 수 없습니다. 따라서 1 단계에서 계산 한 내용을 바탕으로 2 단계에서 flowstep을 구성 할 수는 없습니다 (물론 springbatch 구조 내부를 해킹하여 직접 콩을 수정하면되지만, t는 그것을하고 싶어한다).
필자는 일을 구성하는 클래스에 주입되는 적절한 postConstruct 메서드와 함께 일종의 "SetupBean"을 사용하는 것이 좋습니다. 이 "SetupBean"은 처리중인 개체의 목록을 계산합니다.
@Component public class SetUpBean { private List<Object> myObjects; @PostConstruct public afterPropertiesSet() { myObjects = ...; } public List<Object> getMyObjects() { return myObjects; } } @Configuration public class JobConfiguration { @Autowired private JobBuilderFactory jobBuilderFactory; @Autowired private StepBuilderFactory stepBuilderFactory; @Autowired private SetUpBean setup; ... }
from https://stackoverflow.com/questions/38949030/spring-batch-execute-dynamically-generated-steps-in-a-tasklet by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] MQueue 리스너를 중지 할 수 없습니다. (0) | 2019.02.22 |
---|---|
[SPRING] 봄철 콩 오류 (0) | 2019.02.22 |
[SPRING] Spring-MVC : 훌륭한 인프라 (컨피규레이션) 생성 및 중복 방지 (0) | 2019.02.22 |
[SPRING] @Column insertable, updatable은 Spring JPA와 잘 어울리지 않습니까? (0) | 2019.02.22 |
[SPRING] Spring-Data-Elasticsearch 설정 : Spring은 설정 파일을 찾을 수 없습니까? (0) | 2019.02.22 |