spring-bootspring-integrationspring-batchspring-integration-dslpoller

Spring batch job should be executed only once after the spring integration file poller polls the files


I am trying to poll the files from system folder where one or files may come, for those files, I have to trigger the batch job only once not the number of times equals to the number of files in the folder. In my case my batch is taking care the multiple files at a time, i just want poller to send the signal to batch only once to start its job.

Tried poller.maxMessagesPerPoll(1) etc but its something different.. I am facing the issue where the batch job is getting triggered equals to the number of files the poller gets in the polling folder. I want to execute batch only once

@Bean
public FileMessageToJobRequest fileMessageToJobRequest() {
    FileMessageToJobRequest fileMessageToJobRequest = new FileMessageToJobRequest();
    fileMessageToJobRequest.setJob(fileMessageBatchJob);
    return fileMessageToJobRequest;
}
@Bean
public JobLaunchingGateway jobLaunchingGateway() {
    SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher();
    simpleJobLauncher.setJobRepository(jobRepository);
    simpleJobLauncher.setTaskExecutor(new SyncTaskExecutor());
    JobLaunchingGateway jobLaunchingGateway = new JobLaunchingGateway(simpleJobLauncher);
    return jobLaunchingGateway;
}
@Bean
public IntegrationFlow integrationFlow(JobLaunchingGateway jobLaunchingGateway) {
    System.out.println("&&&&&&&&&&&&&&&&&&Inside Integration Flow!!!!");
    return IntegrationFlows
            .from(Files.inboundAdapter(new File("C:\\apps_data\\recv")),
                    c -> c.poller(Pollers.fixedDelay(1000).maxMessagesPerPoll(1)))
            .filter(onlyT4F2())
            .handle(fileMessageToJobRequest)
            .handle(jobLaunchingGateway)
            .log(LoggingHandler.Level.WARN, "headers.id + ': ' + payload").get();
}

@Bean
public GenericSelector<File> onlyT4F2() {
    System.out.println("@@@@@@@Inside GenericSelector of XXX");
    return new GenericSelector<File>() {
        @Override
        public boolean accept(File source) {
          return source.getName().contains("XXX");
        }
    };
}

Current behavior - When poller detects the file/files on given location the configured batch job triggers that many times. If files are 4 then batch job triggers 4 times.

Expected behavior - After file polling, the batch job should be get executed only once for any number of files. Because the batch job is processing the multiple files at a time hence multiple times execution is unnecessary.

Let me know if you will need any other information from my end. Please help needed on priority


Solution

  • You can use a custom FileListFilter on the inbound channel adapter which only returns one file.

    .filter(myFilterThatOnlyReturnsOneFile)
    

    EDIT

    public class OnlyOneFileListFilter implements FileListFilter<File> {
    
        @Override
        public List<File> filterFiles(File[] files) {
            return Collections.singletonList(files[0]);
        }
    
    }
    
            return IntegrationFlows
                    .from(Files.inboundAdapter(new File("C:\\apps_data\\recv"))
                                .filter(new OnlyOneFileListFilter()),
                            c -> c.poller(Pollers.fixedDelay(1000).maxMessagesPerPoll(1)))
                    ...