【问题标题】:Is there a way to catch SkipLimitExceedException in spring batch有没有办法在春季批次中捕获 SkipLimitExceedException
【发布时间】:2019-08-25 18:17:09
【问题描述】:

我正在使用 multiResourceItemReader 读取 csv 文件,并且我将跳过限制保持为 10。当超过限制时,我想捕获 SkipLimitExceedException 并抛出我自己的自定义异常,并显示类似“无效”的消息csv" ,我在哪里或如何捕捉它?

try {
      log.info("Running job to insert batch fcm: {} into database.", id);
            jobLauncher
                    .run(importJob, new JobParametersBuilder()
                    .addString("fullPathFileName", TMP_DIR)
                    .addString("batch_fcm_id", String.valueOf(id))
                    .addLong("time",System.currentTimeMillis())
                    .toJobParameters());
        }
catch(...){...}

我在这里抓不到,是不是因为我使用的是MultiResourceItemReader,而异步进程不允许我在这里抓到?

我的工作如下

@Bean(name = "fcmJob")
    Job importJob(@Qualifier(MR_ITEM_READER) Reader reader,
                  @Qualifier(JDBC_WRITER) JdbcBatchItemWriter jdbcBatchItemWriter,
                  @Qualifier("fcmTaskExecutor") TaskExecutor taskExecutor) {
        Step writeToDatabase = stepBuilderFactory.get("file-database")//name of step
                .<FcmIdResource, FcmIdResource>chunk(csvChunkSize) // <input as, output as>
                .reader(reader)
                .faultTolerant()
                .skipLimit(10)
                .skip(UncategorizedSQLException.class)
                .noSkip(FileNotFoundException.class)
                .writer(jdbcBatchItemWriter)
                .taskExecutor(taskExecutor)
                .throttleLimit(20)
                .build();

        return jobBuilderFactory.get("jobBuilderFactory") //Name of job builder factory
                .incrementer(new RunIdIncrementer())
                .start(writeToDatabase)
                .on("*")
                .to(deleteTemporaryFiles())
                .end()
                .build();
    }

我尝试过使用ItemReaderListener、SkipPolicy、SkipListener,但是它们不能抛出异常,有没有其他方法?

【问题讨论】:

    标签: spring-boot spring-batch


    【解决方案1】:

    您要查找的异常不是由作业引发的,您可以使用JobExecution#getAllFailureExceptions 从作业执行中获取它。

    所以在你的例子中,而不是这样做:

    try {
        jobLauncher.run(job, new JobParameters());
    } catch (Exception e) {
       //...
    }
    

    你应该这样做:

    JobExecution jobExecution = jobLauncher.run(job, new JobParameters());
    List<Throwable> allFailureExceptions = jobExecution.getFailureExceptions();
    

    在您的情况下,SkipLimitExceedException 将是 allFailureExceptions 之一。

    编辑:添加一个示例,表明SkipLimitExceedExceptionallFailureExceptions 的一部分:

    import java.util.Arrays;
    import java.util.List;
    
    import org.springframework.batch.core.Job;
    import org.springframework.batch.core.JobExecution;
    import org.springframework.batch.core.JobParameters;
    import org.springframework.batch.core.Step;
    import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
    import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
    import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
    import org.springframework.batch.core.launch.JobLauncher;
    import org.springframework.batch.item.ItemProcessor;
    import org.springframework.batch.item.ItemReader;
    import org.springframework.batch.item.ItemWriter;
    import org.springframework.batch.item.support.ListItemReader;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @EnableBatchProcessing
    public class MyJob {
    
        @Autowired
        private JobBuilderFactory jobs;
    
        @Autowired
        private StepBuilderFactory steps;
    
        @Bean
        public ItemReader<Integer> itemReader() {
            return new ListItemReader<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
        }
    
        @Bean
        public ItemProcessor<Integer, Integer> itemProcessor() {
            return item -> {
                if (item % 3 == 0) {
                    throw new IllegalArgumentException("no multiples of three here! " + item);
                }
                return item;
            };
        }
    
        @Bean
        public ItemWriter<Integer> itemWriter() {
            return items -> {
                for (Integer item : items) {
                    System.out.println("item = " + item);
                }
            };
        }
    
        @Bean
        public Step step() {
            return steps.get("step")
                    .<Integer, Integer>chunk(2)
                    .reader(itemReader())
                    .processor(itemProcessor())
                    .writer(itemWriter())
                    .faultTolerant()
                    .skip(IllegalArgumentException.class)
                    .skipLimit(2)
                    .build();
        }
    
        @Bean
        public Job job() {
            return jobs.get("job")
                    .start(step())
                    .build();
        }
    
        public static void main(String[] args) throws Exception {
            ApplicationContext context = new AnnotationConfigApplicationContext(MyJob.class);
            JobLauncher jobLauncher = context.getBean(JobLauncher.class);
            Job job = context.getBean(Job.class);
            JobExecution jobExecution = jobLauncher.run(job, new JobParameters());
            List<Throwable> allFailureExceptions = jobExecution.getAllFailureExceptions();
            for (Throwable failureException : allFailureExceptions) {
                System.out.println("failureException = " + failureException);
            }
        }
    
    }
    

    此示例打印:

    item = 1
    item = 2
    item = 4
    item = 5
    item = 7
    item = 8
    failureException = org.springframework.batch.core.step.skip.SkipLimitExceededException: Skip limit of '2' exceeded
    

    【讨论】:

    • 我试过了,我在日志中得到了 SkipLimit 异常,但是 allFailureExceptions 是空的,没有对象。我还尝试在作业本身中使用.exceptionhandler(),它被捕获但handleException 运行了很多时间。
    • but, the allFailureExceptions is empty, 我在答案中添加了一个示例,表明它应该在那里。可能它在您的代码中的某个地方被吞没了。
    • 可能是因为.start(writeToDatabase) .on("*") .to(deleteTemporaryFiles()) 行,因为即使deleteTemporaryFiles tasklet 运行了任何事情,所以我吞下了异常。
    • 这可能是原因,但我不确定,因为我无法运行您的代码。如果我的回答回答了你的问题,请accept it
    • 谢谢您,先生!我试图解决它,使用 stepexecution 并检查它是否被 ABANDONED。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-25
    • 1970-01-01
    相关资源
    最近更新 更多