spring-bootspring-batchspring-batch-tasklet

Send data to Spring Batch Item Reader (or Tasklet)


I have the following requirement:

  1. An endpoint http://localhost:8080/myapp/jobExecution/myJobName/execute which receives a CSV and use univocity to apply some validations and generate a List of some pojo.
  2. Send that list to a Spring Batch Job for some processing.
  3. Multiple users could do this.

I want to know if with Spring Batch I can achieve this?

I was thinking to use a queue, put the data and execute a Job that pull objects from that queue. But how can I be sure that if other person execute the endpoint and other Job is executing, Spring Batch Knows which Item belongs to a certain execution?


Solution

  • You can use a queue or go ahead to put the list of values that was generated after the step with validations and store it as part of job parameters in the job execution context.

    Below is a snippet to store the list to a job context and read the list using an ItemReader.

    Snippet implements StepExecutionListener in a Tasklet step to put List which was constructed,

    @Override
    public ExitStatus afterStep(StepExecution stepExecution) {
        //tenantNames is a List<String> which was constructed as an output of an evaluation logic
        stepExecution.getJobExecution().getExecutionContext().put("listOfTenants", tenantNames); 
        return ExitStatus.COMPLETED;
    }
    

    Now "listOfTenants" are read as part of a Step which has Reader (To allow one thread read at a time), Processor and Writer. You can also store it as a part of Queue and fetch it in a Reader. Snippet for reference,

    public class ReaderStep implements ItemReader<String>, StepExecutionListener {
    
       private List<String> tenantNames;
    
       @Override
       public void beforeStep(StepExecution stepExecution) {
    
           try {
               tenantNames = (List<String>)stepExecution.getJobExecution().getExecutionContext()
                    .get("listOfTenants");
               logger.debug("Sucessfully fetched the tenant list from the context");
           } catch (Exception e) {
               // Exception block
           }
       }
    
       @Override
       public synchronized String read() throws Exception {
    
          String tenantName = null;
    
           if(tenantNames.size() > 0) {
              tenantName = tenantNames.get(0);
              tenantNames.remove(0);
              return tenantName;
           }
    
           logger.info("Completed reading all tenant names");
           return null;
       }
    
       // Rest of the overridden methods of this class..
    }