0
votes

I have situation that I fail to understand about Kotlin's apply method used on a Reactor Mono object. When from within the apply method, I call methods of the mono object, the called Mono methods don't respond at all.

Example without apply (working as expected):

reactor.core.publisher.Mono
    .just(1)
    .doOnSuccessOrError { i, t ->
        println("doOnSuccessOrError")
    }
    .subscribe {
        println("subscribe: value=$it")
    }

Which produces the console output:

doOnSuccessOrError
subscribe: value=1

As expected, first doOnSuccessOrError() is called, then subscribe().

Example with apply (works not as expected):

reactor.core.publisher.Mono
    .just(1)
    .apply {
        println("Apply")
        doOnSuccessOrError { i, t ->
            println("doOnSuccessOrError")
        }
    }
    .subscribe {
        println("subscribe: value=$it")
    }

Which produces the console output:

Apply
subscribe: value=1

Now it isn't printing "doOnSuccessOrError" anymore, which is the opposite from what I would expect. Why isn't it printed?

1
Use run instead of applyEpicPandaForce

1 Answers

1
votes

This question isn't specific to Mono, but I failed to reproduce it using a simpel test class to generalize the problem. But after reading Kotlin apply on String not working as expected, I understood that it (ofcourse) is caused by immutability of Mono, which also applies to Strings.

So in this code:

monoObject.apply {
    println("Apply")
    doOnSuccessOrError { i, t ->
        println("doOnSuccessOrError")
    }
}

apply is returning the same object as the variable monoObject is referring to. But because of the immutability of Mono, a call to doOnSuccessOrError() is returning a new Mono object, which differs from the one monoObject is referring to. Since the result of doOnSuccessOrError() (a new Mono object) isn't stored at all, the lambda that was given to it won't be called. Which explains the question.

A solution is to use Kotlin's run instead by simply replacing "apply" with "run".