spring-boot - 作业参数未注入,skiplistener 在 spring 批处理中不工作
问题描述
第一个问题是当我打印作业参数“errorPathFile”值时,它为空。
@Component
@Scope(value = "step")
public class EmployeeFieldSetMapper implements FieldSetMapper<Employee> {
@Value("#{jobParameters['errorFilePath']}")
private String filePath; //="C:\\Users\\prajjwal\\Documents\\errorReports.csv";
@Override
public Employee mapFieldSet(FieldSet fieldSet) throws BindException {
final Employee employee = new Employee();
employee.setEmployeeId(fieldSet.readLong("employeeId"));
employee.setEmployeeName(fieldSet.readString("employeeName"));
employee.setAge(fieldSet.readInt("age"));
employee.setPincode(fieldSet.readInt("pincode"));
if(fieldSet.readInt("age")==4) {
try {
System.out.println("errorFilePath"+filePath);
FileWriter skipReport= new FileWriter(filePath, true);
skipReport.append("fromRead,age is 4");
skipReport.close();
}
catch(IOException e) {
throw new RuntimeException();
}
throw new MyException("age is incorrect"+fieldSet.readString("age"));
}
return employee;
}
}
这是我注入价值的方式:
@RestController
@RequestMapping("/api")
public class EmployeeResource {
@Autowired
EmployeeService employeeService;
@Value("${errorFilePath}")
private String errorFilePath;
@Autowired
Job job;
@Autowired
JobLauncher joblauncher;
@GetMapping("/batch")
public ResponseEntity<?> luanch(@RequestParam("file-path") String filePath)
throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException,
JobParametersInvalidException {
return ResponseEntity.ok(joblauncher.run(job, new JobParametersBuilder().addDate("date", new Date())
.addString("filePath", filePath).addString("errorFilePath", errorFilePath).toJobParameters()).getStatus());
}
}
第二个问题是SkipListener
不调用跳过:
@Component
@StepScope
public class MySkipListener implements SkipListener<Employee, Employee> {
@Value("#{jobParameters['errorFilePath']}")
private String filePath;//="abc";
@Override
//@OnSkipInRead
public void onSkipInRead(Throwable t) {
if(t instanceof MyException) {
MyException m= (MyException) t;
try {
System.out.println("called");
FileWriter skipReport= new FileWriter(filePath, true);
skipReport.append("fromRead,"+m.getMessage());
skipReport.close();
} catch (IOException e) {
throw new MyException("IOException occured");
}
}
}
@Override
//@OnSkipInWrite
public void onSkipInWrite(Employee item, Throwable t) {
if(t instanceof MyException) {
MyException m= (MyException) t;
try {
System.out.println("called");
FileWriter skipReport= new FileWriter(filePath, true);
skipReport.append("fromWrite,"+m.getMessage());
skipReport.close();
} catch (IOException e) {
throw new MyException("IOException occured");
}
}
}
@Override
//@OnSkipInProcess
public void onSkipInProcess(Employee item, Throwable t) {
System.out.println("innnn");
if(t instanceof MyException) {
MyException m= (MyException) t;
try {
System.out.println("called");
FileWriter skipReport= new FileWriter(filePath, true);
skipReport.append("fromProcess,"+m.getMessage());
skipReport.close();
} catch (IOException e) {
throw new MyException("IOException occured");
}
}
}
}
这是配置文件:
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Bean
@StepScope
public FlatFileItemReader<Employee> reader(@Value ("#{jobParameters[filePath]}") String filePath) {
return new FlatFileItemReaderBuilder<Employee>().name("EmployeeReader")
.resource(new FileSystemResource(new File(filePath))).delimited()
.names(new String[] { "employeeId", "employeeName", "age", "pincode"}).lineMapper(lineMapper())
.fieldSetMapper(new BeanWrapperFieldSetMapper<Employee>() {
{
setTargetType(Employee.class);
}
}).build();
}
@Bean
public LineMapper<Employee> lineMapper() {
final DefaultLineMapper<Employee> defaultLineMapper = new DefaultLineMapper<>();
final DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();
lineTokenizer.setDelimiter(",");
lineTokenizer.setStrict(false);
lineTokenizer.setNames(new String[] { "employeeId", "employeeName", "age", "pincode"});
final EmployeeFieldSetMapper fieldSetMapper = new EmployeeFieldSetMapper();
defaultLineMapper.setLineTokenizer(lineTokenizer);
defaultLineMapper.setFieldSetMapper(fieldSetMapper);
return defaultLineMapper;
}
@Bean
public EmployeeProcessor employeeProcessor() {
return new EmployeeProcessor();
}
@Bean
public JdbcBatchItemWriter<Employee> writer(final DataSource dataSource) {
return new JdbcBatchItemWriterBuilder<Employee>()
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.sql("INSERT INTO employee (employee_id, employee_name,age, pincode) VALUES (:employeeId, :employeeName ,:age, :pincode)")
.dataSource(dataSource).build();
}
@Bean
public Job importEmployeeJob(NotificationListener listener, Step step1) {
return jobBuilderFactory.get("importEmployeeJob").incrementer(new RunIdIncrementer()).listener(listener)
.flow(step1).end().build();
}
@Bean
public Step step1(JdbcBatchItemWriter<Employee> writer) {
return stepBuilderFactory.get("step1")
.<Employee, Employee>chunk(10)
.reader(reader(null)).faultTolerant().skip(MyException.class).skipLimit(Integer.MAX_VALUE).skipPolicy(new FileVerificationSkipper())
.processor(employeeProcessor()).writer(writer)
.listener( new MySkipListener()).build();
}
@Bean
public ErrorTracker getErrorTracker() {
return new ErrorTracker();
}
}
请提出我做错了什么。
更新:第一个问题得到解决,因为我删除@Component
了我使用的注释@StepScop
。但第二个问题:
SkipListener 没有被调用
没有解决
解决方案
由于不正确,您EmployeeFieldSetMapper
的范围@Scope(value = "step")
不正确。根据Javadoc,应该是@Scope(value="step", proxyMode=TARGET_CLASS)
,见https://github.com/spring-projects/spring-batch/issues/3651#issuecomment-587453328。
我建议@StepScope
改用。
作业参数未注入,skiplistener 在 spring 批处理中不工作
这是因为在您的步骤定义中,您正在自己创建一个新的侦听器实例:
.listener( new MySkipListener())
您的侦听器应声明为 spring bean,以便它被代理并正确注入作业参数。
推荐阅读
- c# - 在每种情况下使用 c# 强制关闭后台服务/应用程序
- java - “com.otaliastudios:cameraview:2.0.0-rcl”的Android Gradle依赖错误?
- html - 搜索图标移出 div,在 chrome 中可以正常工作,但在 Mozilla 中不行
- c++ - 设置开始迭代器时无效使用非静态数据成员
- c# - 使用 Frame 在 WPF 应用程序中打开 URL 会在其中打开它
- java - 如何知道具有相同源端点和目标端点的 Apache Camel 组件的执行流程?
- sql - 排序主子
- c++ - 如何找到具有边界点的所有对象的最短边界到边界距离?
- python - 如何使用 vtk 在一行中选择点?
- python - 对数尺度的直方图和核密度