I'm trying to persist a singleton
class and I'd like to ensure it remains singleton. What is the proper method to synchronize method calls in Spring WebFlux
?
I have the following service method:
public Mono<SingletonClass> saveOrUpdate(SingletonClass singletonClass) {
return this.getTheSingletonClass()
.map(someLogicAndSave)
.switchIfEmpty(singletonClassRepository.save(singletonClass);
}
Should I add the synchronized keyword to the saveOrUpdate
method?
- Q: Synchronized method in Spring WebFlux? (Or any Mono/Flux)
- A: If you can, then find a better solution. First of all, do not use
synchronize
keyword when writing with Project reactor. Look at each function as a small part of the stream. Project Reactor gives you tools that have better control over the streams you are trying to synchronize. Much Much better control. Secondly, You shouldn't synchronize anything unless you are mutating something (which you should do it mainly for optimization purposes). Reacting programming is mainly about callbacks; when someone wants the result of the task, the task will run and when the task is finished, someone (not you) will call the function you provided with the result of the task as a parameter. Synchronization means waiting for a thread to finish to do something so the other thread can do that thing also. try to see if you can change your actual logic to be immutable so multiple threads can do that logic concurrently. If not, then keep reading.
When calling saveOrUpdate
, you get back a Mono that represents the result of the task. the actual result will be there only when someone subscribes to the task (===the Mono you got from calling the function saveOrUpdate
). In other words, saveOrUpdate
only returns the description of the stream === what should the stream do (from top to bottom) when someone pushes a new value at the top of the stream.
- Q: Should I add the synchronized keyword to the
saveOrUpdate
method? - A: No. As a conclusion of the above explanation, calling
saveOrUpdate
multiple times won't do much except creating and returning descriptions of streams. The methods that should (maybe) be synchronized are the methods that actually mutate something and may be called concurrently from multiple threads.
By now, you have the basic knowledge of what a stream is. The next step is to learn about multithreading in Project Reactor (The Mono
/Flux
library).
- Q: What is the proper method to synchronize method calls in Spring WebFlux?
- A: I'm not sure I understand what do you exactly mean. Is this question still relevant after everything I explained? If yes, consider rephrase it (edit the question).
Notes:
Expression evaluations in streams:
You should look closely on the expression: singletonClassRepository.save(singletonClass)
in your example. A stream should execute only when someone subscribes to it. In your example, this piece of code is an expression that can and will be evaluated when the method saveOrUpdate
is executing. As a result, part of the stream is executing even before someone subscribes to it (singletonClassRepository.save(singletonClass)
and the rest of the stream will be executed only when someone subscribes to it.
It's not a bad design. But if singletonClassRepository.save(singletonClass)
is doing some mutation, you should consider synchronize the method saveOrUpdate
.
How to synchronize
Only synchronize with one of the tools which Project Reactor provides: concatMap
,flatMap
and so on.