0% found this document useful (0 votes)
27 views9 pages

Async With CompletableFuture

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
27 views9 pages

Async With CompletableFuture

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 9

Async with CompletableFuture

In JDK 1.8, the Future object got an upgrade and it became


a CompletableFuture object which besides Future, also
implements CompletionStage. The CompletionStage offers
a lot of methods for a simplified usage of the responses
computed in different threads and stages. Some of the
most common are thenApply() similar with map() from
Streams, thenAccept() similar with foreach. There are
multiple ways to get a CompletableFuture response, some
of them running the task on a different thread or not, but
one common point and extra functionality from Futures is
that users can treat exceptions if they occur during
computation.

Async with @Async


Another way to implement async is to use the
annotation @Async provided by Spring Framework. Users
can use it only on public methods and can’t call the
methods from the same class where they are defined. Any
code that is inside a method annotated with Async will be
executed in a different thread and can be void or can
return a CompletableFuture. So this an alternative to
creating a CompletableFuture and giving it a method to
run, but in order to be able to use this annotation, another
thing is needed: @EnableAsync on a configuration class.

Pros and cons of asynchronous


Users should think about using asynchronous
programming when wanting to delegate a task to another
thread because it is time consuming or they don’t want the
result of a task to impact the current flow of the
application. In this way users can do multiple things at
once. By using asynchronous users can decouple tasks and
components and it results in a better overall performance
of the application.

Alternatively, users should be aware that debugging is a


little more complicated in a code with asynchronous
methods and even writing tests, but this shouldn’t be an
impediment when choosing a solution.

One last thing


Threads are about workers and async is about tasks!
Certainly! Here's how you can integrate asynchronous processing, CompletableFuture, and Spring
Batch to improve the execution time of your CSV upload operation:

Async Operation with CompletableFuture:

Use @Async annotation in your service method to make it asynchronous.

Wrap the processing logic inside a CompletableFuture to perform the upload operation
asynchronously.

Return a CompletableFuture<Boolean> to indicate the success or failure of the upload operation.

java

Copy code

import org.springframework.scheduling.annotation.Async;

import org.springframework.stereotype.Service;

import org.springframework.web.multipart.MultipartFile;

import java.util.concurrent.CompletableFuture;

@Service

public class StockService {

@Async

public CompletableFuture<Boolean> uploadCSVAsync(MultipartFile file) {

// Async processing logic here

Spring Batch:

Use Spring Batch to process large volumes of data efficiently.

Define a job with steps to read, process, and write data from the CSV file to the database.
Configure chunk-based processing to process data in chunks, reducing memory consumption and
improving performance.

java

Copy code

import org.springframework.batch.core.Job;

import org.springframework.batch.core.Step;

import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;

import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;

import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.multipart.MultipartFile;

@Configuration

@EnableBatchProcessing

public class BatchConfig {

@Autowired

private JobBuilderFactory jobBuilderFactory;

@Autowired

private StepBuilderFactory stepBuilderFactory;

@Bean

public Job csvUploadJob() {

return jobBuilderFactory.get("csvUploadJob")

.start(csvUploadStep())

.build();

}
@Bean

public Step csvUploadStep() {

return stepBuilderFactory.get("csvUploadStep")

.<MultipartFile, Boolean>chunk(10) // Process 10 items at a time

.reader(csvItemReader())

.processor(csvItemProcessor())

.writer(csvItemWriter())

.build();

// Define CSV reader, processor, and writer beans here

Integration:

Trigger the Spring Batch job asynchronously from your controller or service method using
CompletableFuture.

Monitor the completion of the job and handle the response accordingly.

java

Copy code

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.http.ResponseEntity;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;

import java.util.Map;

import java.util.concurrent.CompletableFuture;

@Controller

public class TestController {

@Autowired
private StockService stockService;

@PostMapping("/upload-csv")

public ResponseEntity<Map<String, Object>> uploadCSV(@RequestParam("file") MultipartFile file)


{

Map<String, Object> response = new HashMap<>();

try {

if (file.isEmpty()) {

response.put("success", false);

response.put("message", "Please select a file to upload.");

return ResponseEntity.badRequest().body(response);

CompletableFuture<Boolean> uploadResult = stockService.uploadCSVAsync(file);

uploadResult.thenAccept(success -> {

if (success) {

response.put("success", true);

response.put("message", "File uploaded successfully!");

} else {

response.put("success", false);

response.put("message", "Failed to process the file.");

});

return ResponseEntity.ok().body(response);

} catch (Exception e) {

response.put("success", false);

response.put("message", "An error occurred while uploading the file.");

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);

}
}

By leveraging asynchronous processing with CompletableFuture and integrating Spring Batch for
batch processing, you can significantly improve the execution time and scalability of your CSV upload
operation.

Today

@Service

public class StockService {

@Autowired

private JobLauncher jobLauncher;

@Autowired

private Job job;

public void uploadCSV(MultipartFile file) {

try {

// Save the uploaded file temporarily

byte[] bytes = file.getBytes();

Path path = Paths.get("temp.csv");

Files.write(path, bytes);

// Trigger Spring Batch job to process the uploaded file

jobLauncher.run(job, new JobParametersBuilder()

.addString("filePath", path.toAbsolutePath().toString())

.toJobParameters());

// Delete the temporary file after processing

Files.deleteIfExists(path);

} catch (Exception e) {
// Handle exception

e.printStackTrace();

You might also like