Search code examples
springspring-bootspring-batchbatch-processing

spring boot handling big request body - processing bulk through multithreading


I have one spring boot controllers which recives many users like below

sample json

{
  "users": [
    { "name":"john", "age":18, "type":"1"},
    { "name":"kim", , "age":18, "type":"2"},
    { "name":"Fits", "age":18, "type","3"},
  ]
 }

request handler

@RequestMapping(value = "/users", method = RequestMethod.POST, headers = "Accept=application/json")
public void Add(@RequestBody List<user> users) throws Exception {

 // Here I am iterating users and writing one by one to different message topic based on the type
 // if any error in the given user while writing to message topic I am storing that user in other DB


}

it works well when I have some 100 users in the user list, but if list is big like 1000 etc it takes too much time. so is there any spring batch job where I can assign to that to perform this?

I just want to return http response code 202 to request and assign this payload to spring batch job


Solution

  • One option is to use Spring Async Task for long running processes in separate thread, hence wouldn't wait to execute whole request and send response back.

    First configure Async task like this.

    @Configuration
    @EnableAsync
    public class AsynchTaskConfiguration{
    
        @Bean
        public Executor taskExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(2);
            executor.setMaxPoolSize(2);
            executor.setQueueCapacity(500);
            executor.setThreadNamePrefix("ProcessUsers-");
            executor.initialize();
            return executor;
        }
    }
    

    And Here you can use Async task in your service for processing users

    @Service
    public class UserProcessingService {
    
    
        private final AnotherUserProcessingService service;
        @Autowired
        public UserProcessingService (AnotherUserProcessingService service) {
            this.service= service;
        }
    
        @Async
        public CompletableFuture<List<User>> processUser(List<User> users) throws InterruptedException {
    
            users.forEach(user -> logger.info("Processing " + user));
            List<User> usersListResult = service.process(users);
            // Artificial delay of 1s for demonstration purposes
            Thread.sleep(1000L);
            return CompletableFuture.completedFuture(usersListResult);
        }
    
    }
    

    processUser(User user) is annotated with @Async indicating the method will run in separate thread according to taskExecutor configuration provided above. @EnableAsync enable Spring to run any method in background thread that is annotated with @Async. And make sure your service using async task to process users must be created inside a @Configuration class or picked up by @ComponentScan. You can customize your taskExecutor according to your needs.

    Here you can find How ThreadPoolTaskExecutor works.