flatMapvsflatMapMany
In functional programming, flatMap returns the same type than the type that bear the method, so for Mono<T>, flatMap returns a Mono. Which means that only one element can be emitted by the inner Publisher (or that it is truncated). We enforced that by having Mono#flatMap take a Function<T, Mono<R>>.
As a consequence, we needed an alternative for more arbitrary Publisher that could emit more than one element. Hence Mono#flatMapMany(Function<T, Publisher<R>>) which returns a Flux<R>.
TL;DR: Mono#flatMap is for asynchronous but 1-to-1 transformation of the element in the source Mono, Mono#flatMapMany is for 1-to-N asynchronous transformation (like Flux#flatMap).
then,thenEmptyandthenMany
All the thenXXX methods on Mono have one semantic in common: they ignore the source onNext signals and react on completion signals (onComplete and onError), continuing the sequence at this point with various options. As a consequence, this can change the generic type of the returned Mono:
thenwill just replay the source terminal signal, resulting in aMono<Void>to indicate that this never signals anyonNext.thenEmptynot only returns aMono<Void>, but it takes aMono<Void>as a parameter. It represents a concatenation of the source completion signal then the second, empty Mono completion signal. In other words, it completes when A then B have both completed sequentially, and doesn’t emit data.thenManywaits for the source to complete then plays all the signals from itsPublisher<R>parameter, resulting in aFlux<R>that will “pause” until the source completes, then emit the many elements from the provided publisher before replaying its completion signal as well.