Reputation: 557
I have to upload CSV, convert it to Java Object and then persist in Database. I am using Spring Boot with Spring Batch to achieve this. I have gone through multiple tutorials. After analyzing those it seems Spring Batch Job run asynchronously as response sent to client before job completion. But I need to send response to client after job execution completed. Is it possible to do? Please help to resolve this issue. Thanks My Controller Code follows:
@RestController
public class AppRestCtrl {
Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
JobLauncher jobLauncher;
@Autowired
Job job;
@PostMapping("/processFile")
public ResponseEntity convertCsvToObject(@RequestParam("fileData") MultipartFile file) throws Exception {
final Path rootLocation = Paths.get("uploads");
if(!Files.exists(rootLocation)) {
Files.createDirectories(rootLocation);
}
if(file.isEmpty()) {
return ResponseEntity.badRequest().body("Empty File Not Allowed");
}
if(!file.getOriginalFilename().contains(".csv")) {
return ResponseEntity.badRequest().body("File is Invalid!");
}
Files.deleteIfExists(rootLocation.resolve(file.getOriginalFilename()));
Files.copy(file.getInputStream(), rootLocation.resolve(file.getOriginalFilename()));
try {
JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis())
.toJobParameters();
jobLauncher.run(job, jobParameters);
} catch (Exception e) {
logger.info(e.getMessage());
return ResponseEntity.ok("Batch Process Started Successfully!");
}
}
Batch Config File:
@Configuration
public class BatchConfig {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Bean
public Job job() {
return jobBuilderFactory.get("job").incrementer(new RunIdIncrementer()).listener(new Listener())
.flow(step1()).end().build();
}
@Bean
public Step step1() {
return stepBuilderFactory.get("step1").<ObjectNode, JsonNode>chunk(1)
.reader(Reader.reader("uploads\\students.csv"))
.processor(new Processor()).writer(new Writer()).build();
}
}
Upvotes: 1
Views: 2295
Reputation: 31600
it seems Spring Batch Job run asynchronously as response sent to client before job completion
This is true if the job launcher is configured with an asynchronous task executor. If the job launcher uses a synchronous task executor (which is the default), the job will be executed until completion. But in this case, the web client will be waiting until the job is completed which is probably what you don't want to happen (more details here: https://docs.spring.io/spring-batch/4.0.x/reference/html/job.html#runningJobsFromWebContainer).
I need to send response to client after job execution completed
If your job execution time is fast enough to be acceptable as an execution time for a web request, then you can use the (default) synchronous task executor. In this case, you can send the response after job is completed. But as said, this is not recommended for long running jobs as the http request may timeout before the job is finished.
Trying to use a org.springframework.web.context.request.async.DeferredResult
(or a similar approach) would be an ugly hack as it does not solve the problem. So I don't see a viable option for your use case.
Upvotes: 1