Home > Software engineering >  Spring Boot Batch Automatically run instead of sending a request. How can I fix it?
Spring Boot Batch Automatically run instead of sending a request. How can I fix it?

Time:09-29

I have an issue regarding running batch process through a request instead of run it automatically when the application runs.

Normally, when I start the application, batch process automatically is handled and it allows to save all values into database. I don't want to do that.

After I want to make a request defined in controller, batch process will starts. It is what I really want to do.

How can I do that?

Here is the project link : Link

Here is the BatchConfiguration class shown below.

@Configuration // Informs Spring that this class contains configurations
@EnableBatchProcessing // Enables batch processing for the application
@RequiredArgsConstructor
public class BatchConfiguration {

    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;
    private final UserRepository userRepository;

    @Bean
    public FlatFileItemReader<UserInput> reader() {
        FlatFileItemReader<UserInput> itemReader = new FlatFileItemReader<>();
        itemReader.setResource(new FileSystemResource("src/main/resources/MOCK_DATA.csv"));
        itemReader.setName("csvReader");
        itemReader.setLinesToSkip(1);
        itemReader.setLineMapper(lineMapper());
        return itemReader;
    }

    private LineMapper<UserInput> lineMapper() {
        DefaultLineMapper<UserInput> lineMapper = new DefaultLineMapper<>();

        DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();
        lineTokenizer.setDelimiter(",");
        lineTokenizer.setStrict(false);
        lineTokenizer.setNames(
                "personId","firstName","lastName","email","gender","birthday","country"
        );

        BeanWrapperFieldSetMapper<UserInput> fieldSetMapper = new BeanWrapperFieldSetMapper<>();
        fieldSetMapper.setTargetType(UserInput.class);

        lineMapper.setLineTokenizer(lineTokenizer);
        lineMapper.setFieldSetMapper(fieldSetMapper);
        return lineMapper;
    }

    @Bean
    public UserProcessor processor() {
        return new UserProcessor();
    }

    @Bean
    public RepositoryItemWriter<User> writer() {
        RepositoryItemWriter<User> writer = new RepositoryItemWriter<>();
        writer.setRepository(userRepository);
        writer.setMethodName("save");
        return writer;
    }

    @Bean
    public Step step1() {
        return stepBuilderFactory.get("csv-step").<UserInput, User>chunk(10)
                .reader(reader())
                .processor(processor())
                .writer(writer())
                .listener(stepExecutionListener())
                .taskExecutor(taskExecutor())
                .build();
    }

    @Bean
    public Job runJob() {
        return jobBuilderFactory.get("importuserjob")
                .listener(jobExecutionListener())
                .flow(step1()).end().build();

    }

    @Bean
    public TaskExecutor taskExecutor() {
        SimpleAsyncTaskExecutor asyncTaskExecutor = new SimpleAsyncTaskExecutor();
        asyncTaskExecutor.setConcurrencyLimit(10);
        return asyncTaskExecutor;
    }

    @Bean
    public UserJobExecutionNotificationListener stepExecutionListener() {
        return new UserJobExecutionNotificationListener(userRepository);
    }


    @Bean
    public UserStepCompleteNotificationListener jobExecutionListener() {
        return new UserStepCompleteNotificationListener();
    }
}

Here is the controller class shown below.

public class BatchController {

    private final JobLauncher jobLauncher;
    private final Job job;

    @PostMapping("/importuserjob")
    public ResponseEntity<String> importCsvToDBJob() {

        log.info("BatchController | importCsvToDBJob is called");

        JobParameters jobParameters = new JobParametersBuilder()
                .addLong("startAt", System.currentTimeMillis()).toJobParameters();
        try {
            jobLauncher.run(job, jobParameters);
        } catch (JobExecutionAlreadyRunningException | JobRestartException |
                 JobInstanceAlreadyCompleteException | JobParametersInvalidException e) {
            log.info("BatchController | importCsvToDBJob | error : "   e.getMessage());
            e.printStackTrace();
        }

        return new ResponseEntity<>("Batch Process started!!", HttpStatus.OK);
    }
}

CodePudding user response:

To stop the job running automatically set the following config flag

spring:
  batch:
    job:
      enabled: false

you can always set the value at launch if you are running a jar

java -Dspring.batch.job.enabled=false -jar myapp.jar

Not sure if it's just a cut and paste issue, but you are missing a constructor in your controller which is required to set final variables, joblauncher and job. Also I assume your controller has @Controller & @Slf4j annotations

  • Related