Locking In Spring Boot Web flux
Spring Boot Web Flux works asynchronously, so applying locks in this might be a bit difficult. This article will tell you or give you an idea that how we can apply different locking mechanism in spring web flux. So lets get started…
Why locking in web flux different to spring boot?
Well we have blocking calls in spring boot, so locking applied on spring boot works fine as 1 thread is working on serving that request. But In case of web flux we have multiple threads concurrently working on the particular part of code. Additionally we use Mono & Flux to serve this purpose in spring web flux. Chaining of Mono and Flux in code causes problem that where to put locking object so that it properly locks our common resource and one thread can work on it at a time.
Lets see that in a sample code
@Configuration
public class Config {
int id = 1;
ReentrantLock lock = new ReentrantLock();
@Bean
public RouterFunction<ServerResponse> routeToHandler() {
return route(GET("/check"), (request) -> handleCall());
}
public Mono<ServerResponse> handleCall() {
//Applying the lock in starting
lock.lock();
System.out.println("Starting Time : " + (LocalDateTime.now()));
//Chaining MONO's to access common resource
return Mono.just(1).flatMap(value-> {
return Mono.just(2).flatMap(value2 -> {
try {
return Mono.just(value2 + getValue()).flatMap(value3 -> {
//Do Some Work Here
System.out.println("Ending Time : " + (LocalDateTime.now()));
//Unlock
lock.unlock();
return ServerResponse.ok().bodyValue(value3);
});
} catch (InterruptedException e) {
// Unlocking lock at every possible place where exception can occur
System.out.println("Exception :: " + e);
lock.unlock();
return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR).bodyValue("Error");
}
}).onErrorResume(err -> {
// Unlocking lock at every possible place where exception can occur
lock.unlock();
return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR).bodyValue("Error");
}).onErrorResume(err -> {
// Unlocking lock at every possible place where exception can occur
lock.unlock();
return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR).bodyValue("Error");
});
});
}
public int getValue() throws InterruptedException {
//Do Some Work Here
Thread.sleep(3000);
return ++id;
}
In this snippet we are apply lock in Mono, basically on chain of Mono and we are unlocking the lock on different scenarios. These scenarios can be success case or failure case, so make sure that you unlock the lock in every case as per your code logic.
Thanks .. Hope it will be useful for you… :)