簡體   English   中英

Spring Batch 3.0:StepExecutionListener 用於分區 Step 並將執行上下文值級聯到分區作業

[英]Spring Batch 3.0 : StepExecutionListener for a partitioned Step and cascading of execution context values to the partitioned job

給定一個使用分區的Spring 批處理作業:

<job id="reportingJob" xmlns="http://www.springframework.org/schema/batch">
        <batch:listeners>
            <batch:listener ref="reportingJobExecutionListenerr" />
        </batch:listeners>
        <batch:step id="reportingMasterStep">
            <partition step="reportingSlaveStep"
                partitioner="reportingPartitioner">
                <batch:handler grid-size="10" task-executor="taskExecutor" />
            </partition>
        </batch:step>
</job>

reportingSlaveStep定義為:

<step id="reportingSlaveStep" xmlns="http://www.springframework.org/schema/batch">
        <job ref="reportingSlaveJob" />
</step>

reportingSlaveJob定義為:

    <job id="reportingSlaveJob" xmlns="http://www.springframework.org/schema/batch">
        <batch:listeners>
            <batch:listener ref="reportsOutputListener" />
        </batch:listeners>
        <batch:split id="reportsCreationSplit"
            task-executor="taskExecutor">
            <batch:flow>
                <batch:step id="basicReportStep">
                    <tasklet throttle-limit="5" task-executor="taskExecutor">
                        <batch:chunk reader="basicReportReader"
                            writer="basicReportWriter" commit-interval="500" />
                    </tasklet>
                </batch:step>
            </batch:flow>
            <batch:flow>
                <batch:step id="advancedReportStep">
                    <tasklet throttle-limit="5" task-executor="taskExecutor">
                        <batch:chunk reader="advancedReportDataReader" writer="advancedReportWriter"
                            commit-interval="500" />
                    </tasklet>
                </batch:step>
            </batch:flow>
       </batch:split>
     </job>

我現在有兩個問題:

  1. 我想為每個分區創建一個新的reportsOutputListener實例。 我可以通過將reportsOutputListener設置為Step范圍的 bean 來實現這一點嗎?
  2. 我希望能夠訪問為reportingJob創建的相同jobExecutionContext ,以便在reportingSlaveJob中訪問。 我是否需要對此進行任何特殊處理,或者reportingJob是否也使用了reportingSlaveStepSlaveJob中的同一個jobExecutionContext實例?
  3. 編輯:當我運行上述作業時,有時我會收到一個異常,說“該作業的作業執行已經在運行”,有時我會在MapExecutionContextDao.java:130上收到NullPointerException

編輯:另請注意,對於第 2 點, slaveJob無法訪問 reportPartitioner 在stepExecutionContext中添加的值(使用 spring 配置 xml 中#{stepExecutionContext['msbfBatchId']} reportingPartitioner )。 stepExecutionContext中針對鍵的值顯示為null

我想為每個分區創建一個新的 reportsOutputListener 實例。 我可以通過將 reportsOutputListener 設置為 Step 范圍的 bean 來實現這一點嗎?

答案是肯定的。 (如Mahmoud Ben Hassine的評論中所述)

我希望能夠訪問為reportingJob 創建的相同jobExecutionContext,以便在reportingSlaveJob 中訪問。 我是否需要對此進行任何特殊處理,或者reportingSlaveStepSlaveJob 是否也使用了reportingJob 中的同一個jobExecutionContext 實例?

答案是否定的。 我深入研究了Spring 批處理代碼,發現JobStep使用JobParametersExtractor將值從stepExecutionContext復制到JobParameters 這意味着reportingSlaveJob可以從JobParameters而不是StepExecutionContext訪問這些值。 也就是說,出於某種原因, Srping Batch 3.0中的DefaultJobParametersExtractor實現似乎沒有按預期將值復制到jobParameters 我最終編寫了以下自定義提取器:

public class CustomJobParametersExtractor implements JobParametersExtractor {

    private Set<String> keys;

    public CustomJobParametersExtractor () {
        this.keys = new HashSet<>();
    }

    @Override
    public JobParameters getJobParameters(Job job, StepExecution stepExecution) {
        JobParametersBuilder builder = new JobParametersBuilder();
        Map<String, JobParameter> jobParameters = stepExecution.getJobParameters().getParameters();
        ExecutionContext stepExecutionContext = stepExecution.getExecutionContext();
        ExecutionContext jobExecutionContext = stepExecution.getJobExecution().getExecutionContext();

        // copy job parameters from parent job to delegate job
        for (String key : jobParameters.keySet()) {
            builder.addParameter(key, jobParameters.get(key));
        }

        // copy job/step context from parent job/step to delegate job
        for (String key : keys) {
            if (jobExecutionContext.containsKey(key)) {
                builder.addString(key, jobExecutionContext.getString(key));
            } else if (stepExecutionContext.containsKey(key)) {
                builder.addString(key, stepExecutionContext.getString(key));
            } else if (jobParameters.containsKey(key)) {
                builder.addString(key, (String) jobParameters.get(key).getValue());
            }
        }
        return builder.toJobParameters();
    }

    public void setKeys(String[] keys) {
        this.keys = new HashSet<>(Arrays.asList(keys));
    }

}

然后我可以在報告從屬步驟中使用上述提取器,如下所示:

<step id="reportingSlaveStep" xmlns="http://www.springframework.org/schema/batch">
        <job ref="reportingSlaveJob" job-parameters-extractor="customJobParametersExtractor"/>
</step>

其中customJobParametersExtractorCustomJobParametersExtractor類型的 bean,它將我們要復制的所有鍵傳遞給reportingSlaveJobJobParameters

當我運行上述作業時,有時我會收到一個異常說“該作業的作業執行已經在運行”,有時我會在 MapExecutionContextDao.java:130 上收到 NullPointerException

發生這種情況的原因是因為沒有我的CustomJobParameterExtractorreportingSlaveJob會以空JobParameters 對於Spring 批處理創建新的作業實例,每次啟動reportingSlaveJob的作業參數必須不同。 使用CustomJobParameterExtractor解決了這個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM