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

1.5k views Asked by At

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

2

There are 2 answers

3
Gary Russell On BEST ANSWER

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)))
                ...
0
Ganesh On

@Gary Russell - Issue is solved, used the GenericSelector only as below. Thanks for your help. After triggering the batch job on the first run it processes all the present files and moves it to some other folder hence I have added file.exists() and its working well as per my expectations. But I observed that after 1 hour or sometimes the polling is not happening even after providing the expected files, need your help/suggestion on the same.

@Bean
public GenericSelector<File> triggerJobOnlyOnce() {
    return new GenericSelector<File>() {
        @Override
        public boolean accept(File source) {
                if(source.getName().contains("XXX") && source.exists())
                    return true;
            return flag;
        }
    };
}