java flow step,即使步骤完成,使用FlowBuilder的Spring Batch作业也会失败

我有一个Spring批处理作业,它成功完成了这些步骤,但将整个批处理作业状态标记为Failed . 这项工作有两个步骤 . 第一步验证输入文件并为我们正在处理的文件类型设置变量 . 使用Tasklet和JobExecutionDecider会发生这种情况 . 然后,流构建器决定何时执行步骤2的步骤 . 一切运行正常,每一步都完成,但整体批处理状态设置为FAILED而不是COMPLETED .

如果我检查表BATCH_STEP_EXECUTION(SELECT * FROM BATCH_STEP_EXECUTION WHERE JOB_EXECUTION_ID = 54;)中的步骤的状态,我看到这两个步骤都标记为COMPLETED .

知道为什么我的整个批处理工作被认为失败了吗?

这是批处理状态返回的内容:

2018-07-26 15:21:38.132 INFO 95001 --- [ask-scheduler-1] osbclsupport.SimpleJobLauncher:Job:[FlowJob:[name = importEmployees]]使用以下参数完成:[{input.file . name = / Users / aaronradich / Dev / posthire-batch / target / classes / data / import / employees.csv,time = 1532643668685}]及以下状态:[ FAILED ]

这是相关的代码 . 我猜它与FlowBuilder的配置方式有关?:

@Bean

protected Step step1(FlatFileItemReader reader, FileValidationTasklet fileValidationTasklet) {

return steps.get("step1").tasklet(fileValidationTasklet)

.build();

}

@Bean

protected Step step2(FlatFileItemReader reader, EmployeeProcessor processor, EmployeeWriter writer) {

return steps.get("step2")

.chunk(10)

.reader(reader)

.processor(processor)

.writer(writer)

.build();

}

@Bean

public Job importEmployees(@Qualifier("step1") Step step1, @Qualifier("step2") Step step2) {

JobBuilder jobBuilder = jobBuilderFactory

.get("importEmployees")

.incrementer(new RunIdIncrementer());

StepDecider fileDecider = new StepDecider();

Flow flowFile = new FlowBuilder("fileFlow")

.start(fileDecider)

.on(BatchConfig.STATE_DO_FILE_1)

.to(step2)

.on(BatchConfig.STATE_DO_FILE_2)

// TODO: Add an additional Step for File Type 2 (maybe called stepF2, etc.)

.to(step2)

.from(fileDecider)

.on(BatchConfig.STATE_SKIP_FILE)

.end(BatchConfig.STATE_FAILED)

.on("*")

.end(BatchConfig.STATE_COMPLETED)

.build();

/*

* Complete Workflow:

*

* |--> (S2)

* S1 ---> -+

* |--> (S3)

*/

FlowJobBuilder builder = jobBuilder

.flow(step1)

.next(flowFile)

.end();

return builder.build();

}

这是JobExecutionDecider:

package com.sterlingts.posthire.batch;

import org.springframework.batch.core.job.flow.FlowExecutionStatus;

import org.springframework.batch.core.job.flow.JobExecutionDecider;

import com.sterlingts.posthire.batch.config.BatchConfig;

public class StepDecider implements JobExecutionDecider {

@Override

public FlowExecutionStatus decide(org.springframework.batch.core.JobExecution jobExecution,

org.springframework.batch.core.StepExecution stepExecution) {

String fileTypeCode = jobExecution.getExecutionContext().getString("FileTypeCode");

String returnStatus = "";

switch(fileTypeCode) {

case "1":

returnStatus = BatchConfig.STATE_DO_FILE_1;

break;

case "2":

returnStatus = BatchConfig.STATE_DO_FILE_2;

break;

default:

returnStatus = BatchConfig.STATE_SKIP_FILE;

break;

}

return new FlowExecutionStatus(returnStatus);

}

}

这里是TaskLet,它确定文件是否有效,并在JobContext中为我们正在处理的文件类型设置一个变量:

package com.sterlingts.posthire.batch.util;

import java.io.BufferedReader;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.batch.core.BatchStatus;

import org.springframework.batch.core.ExitStatus;

import org.springframework.batch.core.StepContribution;

import org.springframework.batch.core.scope.context.ChunkContext;

import org.springframework.batch.core.step.tasklet.Tasklet;

import org.springframework.batch.repeat.RepeatStatus;

public class FileValidationTasklet implements Tasklet {

private final String FILE_HEADER_1 = "EmployeeId,SSN,FirstName,MiddleName,LastName,Suffix,MaidenName,DOB,Gender,Country,Street,AptNo,City,Region,PostalCode,PhoneDay,PhoneDayExt,PhoneEve,PhoneEveExt,Email,Account,EmployeeStatus,HireDate,StartDate,TerminateDate,DLNumber,DLRegion,LastNameOnLicense,FirstNameOnLicense,MiddleNameOnLicense,JobPosition,BillCode";

private final String FILE_HEADER_2 = "EmployeeId,SSN,FirstName,MiddleName,LastName";

private static final Logger log = LoggerFactory.getLogger(FileValidationTasklet.class);

private String inputFile;

private String fileTypeCode;

public FileValidationTasklet() {

}

public FileValidationTasklet(String inputFile) {

this.inputFile = inputFile;

}

@Override

public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {

System.out.println("Input file is " + inputFile);

if (this.isValidFile()) {

// store the FileTypeCode in the jobExecutionContext so we can access it in other steps

chunkContext

.getStepContext()

.getStepExecution()

.getJobExecution()

.getExecutionContext()

.put("FileTypeCode", this.fileTypeCode);

} else {

throw new Exception("File '" + inputFile + "' is not a valid file format! Aborting import!");

}

// set the exit status for the Tasklet to Completed so the overall job can get completed

//chunkContext.getStepContext().getStepExecution().setExitStatus(ExitStatus.COMPLETED);

chunkContext.getStepContext().getStepExecution().setStatus(BatchStatus.COMPLETED);

// tell Batch to continue on to the next step and not repeat this one

return RepeatStatus.FINISHED;

}

private Boolean isValidFile() {

Boolean validFile = false;

BufferedReader brFile;

try {

brFile = new BufferedReader(new FileReader(inputFile));

String headerRow = brFile.readLine();

// have noticed that sometimes the leading character from the readLine is a space

headerRow = headerRow.trim();

// strip CR and LF just in case the file originated from Windows and still has a CR or LF after the readLine

headerRow = headerRow.replaceAll("\r", "").replaceAll("\n", "");

// remove the leading byte-order mark (BOM) character

headerRow = SpringIntegrationUtils.removeUTF8BOM(headerRow);

if (headerRow.equals(FILE_HEADER_1)) {

this.fileTypeCode = "1";

validFile = true;

} else if (headerRow.equals(FILE_HEADER_2)) {

this.fileTypeCode = "2";

validFile = true;

}

} catch (FileNotFoundException e) {

log.error("File '" + inputFile + "' was not found! Aborting!");

} catch (IOException e) {

log.error("Error validating header row of file '" + inputFile + "'!");

}

return validFile;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值