2016-08-15 106 views
0

我有一個春天的批處理作業,做以下...春季批次執行動態生成的步驟,一個tasklet

步驟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。有人可以告訴我如何執行它們嗎

回答

0

這是行不通的。您的Tasklet只是使用FlowStep創建一個作業作爲第一步。使用jobBuilderfactory只是創建作業。它不會啓動它。方法名稱「開始」可能會引起誤解,因爲這僅僅定義了第一步。但它沒有啓動這項工作。

一旦它開始,您就不能更改作業的結構(其步驟和子步驟)。因此,根據步驟1中計算的內容,不可能在步驟2中配置流程步驟(當然,您可以在彈簧結構內部進行更深入的修改,並直接修改bean等等,不想這樣做)。

我建議你使用一種「SetupBean」和一個適當的postConstruct方法,這個方法被注入你的類來配置你的工作。這個「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; 

    ... 
} 
+0

謝謝。在setupBean中,是否可以使用JobScope註釋訪問jobParameters? – Richie

+0

作業未運行,因此沒有JobScope,因此JobScope註釋將不起作用。你提供jobParameters作爲commandLine-Arguments嗎?你在用SpringBoot來啓動你的工作嗎? –

+0

我是,但我的用戶正在通過休息端點執行作業,所以命令行參數不是一個選項。我可以選擇你的大腦一分鐘,問你是否必須根據數據中的某個關鍵字將讀取器數據分成多個輸出文件,你會怎麼做? – Richie