GISNovis
GISNovis

Reputation: 117

Summarizing data using Spring Batch

I need to have a scheduled process that reports a summary from a large table. When the code runs it will generate a complex summary of current activity on the table. My company is totally committed to using Spring Batch for anything that needs to be scheduled so I have been instructed to use Spring Batch for this. So I am learning Spring Batch while I am attempting to design the solution.

In reading about Spring Batch the documentation I have found says rather bluntly that it was designed to read a record, process that record then write the record. I can find nothing that enables a module to read ALL the data and generate a report. And I can't find any example or tutorial that allows a developer to do this. I have been able to write an item processor that will accumulate the data in class variables the way that I want. (Although I'm not enthusiastic about class variables!) But I don't see a way to call a separate method of the processor to generate the report once all the data is processed. It appears I could save the data in the job context but I don't see a way to tell it to run "class X" when all the data is processed and get the report I need to produce. And that seems to be a really dumb way to program just to make it fit into something that wasn't designed for this purpose.

Does Spring Batch have this sort of capability? If it does, how is it configured?

Upvotes: 1

Views: 1917

Answers (1)

Niсk Vitevskii
Niсk Vitevskii

Reputation: 21

I suppose, in your case, the most suitable is to use Tasklet, instead chunk oriented approach.

As says Spring Batch - Reference Documentation, 5.2. TaskletStep:

Chunk-oriented processing is not the only way to process in a Step. What if a Step must consist as a simple stored procedure call? You could implement the call as an ItemReader and return null after the procedure finishes, but it is a bit unnatural since there would need to be a no-op ItemWriter. Spring Batch provides the TaskletStep for this scenario.

So you can implement Tasklet interface, and put all logic of creating a report in execute method.

@Configuration
@EnableBatchProcessing
public class TaskletsConfig {

    @Autowired
    private JobBuilderFactory jobs;

    @Autowired
    private StepBuilderFactory steps;

    @Bean
    protected Step createReport() {
        return steps
          .get("createReport")
          .tasklet(reportTasklet())
          .build();
    }

    @Bean
    public Job job() {
        return jobs
          .get("createReportJob")
          .start(createReport())
          .build();
    }

    @Bean
    public ReportTasklet reportTasklet(){
        return new ReportTasklet();
    }

    // ...

}  

public class ReportTasklet implements Tasklet {

    @Override
    public RepeatStatus execute(StepContribution stepContribution, 
                                ChunkContext chunkContext) throws Exception {

      // here read all the data and generate a report
      return RepeatStatus.FINISHED;
    }
}

Also, you can split task for few Tasklet steps, of course, if it suitable in your case.

For example:

  • first step - retrive all data;
  • second step - generate a report;
  • third step - save a report;

You can see more examples and details about difference beetween Tasklet approach and chunk oriented approach in this article.

Upvotes: 1

Related Questions