lasnico37
lasnico37

Reputation: 61

How to quit a tasklet if error in Spring Batch?

I would like to quit a tasklet cleanly if I have an error on it and put and stop the batch without having to resort to a System.exit(1).

Here is my code:

/**
     * execution de la tasklet
     *
     */
    @Override
    public RepeatStatus execute(StepContribution arg0, ChunkContext arg1) throws IOException {

        if (suiviFluxDao.getNbFileDateTrt(FilenameUtils.getName(resource), Utils.getDateFromStringFormatUS(dateTraitement)) > 0) {
            LOGGER.info(PropertiesUtils.getLibelleExcep(Constantes.ERREUR_NB_FILE_SELECT,
                    new String[]{ConstantesNomsSql.TABLE_STCO_STAU_SUIVI_FLUX, FilenameUtils.getName(resource), dateTraitement, Constantes.NAME_TRT}));
            System.exit(1);
        } else {
            SuiviFluxBO suiviFluxBO = new SuiviFluxBO();
            suiviFluxBO.setDateSysteme(Utils.getDateTodayFormatUS());
            suiviFluxBO.setDateTrt(Utils.getDateFromStringFormatUS(dateTraitement));
            suiviFluxBO.setLibelleTrt("Batch_Java");
            suiviFluxBO.setNomficTrt(FilenameUtils.getName(resource));
            suiviFluxBO.setNbrrecTrt(Utils.countNbFile(resource));
            suiviFluxBO.setNomtabTrt(ConstantesNomsSql.TABLE_STCO_STAU_FIC_ADH);
            suiviFluxBO.setNbrlignesTrt(0);
            suiviFluxDao.insertSuiviBO(suiviFluxBO);
        }
        // fin de l'execution
        return RepeatStatus.FINISHED;
    }

The tasklet implements StepExecutionListener but how to indicate in the IF that contains the error to modify the execution status so that it is in FAILED?

Thank you for your leads.

Upvotes: 5

Views: 2444

Answers (2)

Deepak Kenchamba
Deepak Kenchamba

Reputation: 21

If your intention is to exit the Tasklet execute() method with ExitStatus.FAILED without throwing an Exception. We have an elegant way of doing it.

chunkContext.getStepContext().getStepExecution().setExitStatus(ExitStatus.FAILED);
chunkContext.getStepContext().getStepExecution().setTerminateOnly();

As per following documentation, setTerminateOnly() signals to the execution environment that this Step execution (and its surrounding job) wishes to exit

https://docs.spring.io/spring-batch/trunk_bkp/apidocs/org/springframework/batch/core/StepExecution.html#setTerminateOnly--

Upvotes: 0

Chandu Allenki
Chandu Allenki

Reputation: 41

Based on above requirement , we can build a flow using spring batch FlowBuilder object .

1 . Build a Tasklet which performs required validations and sets ExitStatus based on validation result.

    @Component
    public class TestTasklet implements StepExecutionListener, Tasklet {

        // Any additional properties if required can be added here .

        @Override
        public void beforeStep(StepExecution stepExecution) {
            // Any logic added here will execute before executing step
        }

        @Override
        public ExitStatus afterStep(StepExecution stepExecution) {
            // Any logic added here will execute after executing step
            return null;
        }

        @Override
        public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws IOException {
            if (suiviFluxDao.getNbFileDateTrt(FilenameUtils.getName(resource),
                    Utils.getDateFromStringFormatUS(dateTraitement)) > 0) {
                LOGGER.info(PropertiesUtils.getLibelleExcep(Constantes.ERREUR_NB_FILE_SELECT,
                        new String[]{ConstantesNomsSql.TABLE_STCO_STAU_SUIVI_FLUX, FilenameUtils.getName(resource),
                                dateTraitement, Constantes.NAME_TRT}));
                 contribution.setExitStatus(ExitStatus.FAILED);
            } else {
                // any logic goes here .
                contribution.setExitStatus(ExitStatus.COMPLETED);
            }
            return RepeatStatus.FINISHED;
        }
    }

2 . Below code snippet allows to configure job using flow builder :

    @Configuration
    public class JobConfigurations {

        private StepBuilderFactory stepBuilderFactory;
        private JobBuilderFactory jobBuilderFactory;

        @Autowired
        public JobConfigurations(StepBuilderFactory stepBuilderFactory,
                                 JobBuilderFactory jobBuilderFactory) {
            this.stepBuilderFactory = stepBuilderFactory;
            this.jobBuilderFactory = jobBuilderFactory;
        }

        @Bean
        public Job job(TestTasklet testTasklet) {
            Step validationStep = stepBuilderFactory.get("validationTasklet")
                    .tasklet(testTasklet).build();

            //create another step where you want to perform business logic
            //for sake of brevity let us assume it to be businessValidationStep
            //Step businessValidationStep = stepBuilderFactory.get("businessvalidationstep")
            //        .chunk().reader().processor().writer();

            return jobBuilderFactory.get("JOB_NAME").incrementer(new RunIdIncrementer())
                    .start(validationStep)// start your job with validation step
                    .on(ExitStatus.FAILED.getExitCode()).end()// this will terminate your job cleanly
                    .from(validationStep)
                    .on(ExitStatus.COMPLETED.getExitCode())//.to("businessValidationStep")
                    .to(validationStep).build().build();
        }

    }

@lasnico37 Hope above code will solve the problem statement .

Upvotes: 4

Related Questions