1

In my Spring Boot project, a couple of REST API endpoints require a class whose initialization takes several minutes. Because of this, it takes several minutes to start the REST API.

Is it possible (using Spring Boot) to make so that these few endpoints are initialized asynchronously i.e. all other endpoints are initialized right away and REST API starts working and these endpoints are initialized whenever the class that they need is initialized and are simply not available to the user before that?

I tried looking into @Async and other ways to make things asynchronous in Spring Boot, but that did not help. I would really appreciate some help. Thank you!

2 Answers2

2

Try @Lazy annotation. When it's applied to the spring component, it will be initialized on the first call.

Some resources:

Petr Aleksandrov
  • 1,100
  • 7
  • 19
  • But then the component won't be initialized automatically and will only start initializing after the first call. I am looking for something that would be able to start the initialization of a component automatically after the REST API starts and while the component is being initialized the endpoints that use this component are not available while all other endpoints are available and working. – Mihhail Sokolov Feb 22 '21 at 17:07
2

There's nothing built into Spring to do what you want, but you could implement it yourself by returning a 404 Not Found response while the service is initializing and a 200 OK once it's available. The following is one way to implement that:

@RestController
class ExampleController {
    
    private final Future<SlowInitializationService> service;
    
    ExampleController() {
        this.service = ForkJoinPool.commonPool().submit(SlowInitializationService::new);
    }
    
    @GetMapping
    ResponseEntity<Result> example() throws InterruptedException, ExecutionException {
        if (this.service.isDone()) {
            return new ResponseEntity<>(this.service.get().perform(), HttpStatus.OK);
        }
        return new ResponseEntity<>(HttpStatus.NOT_FOUND);
    }
    

}

Rather than using the common pool, you may want to inject an Executor or similar. It'll depend on the rest of your app and how it handles threading.

Andy Wilkinson
  • 85,432
  • 19
  • 215
  • 204
  • The following thread can be helpful to decide which HTTP code to return while the service is initializing: https://stackoverflow.com/q/9794696/5990117 – Petr Aleksandrov Feb 23 '21 at 10:02