What is the principal difference between these in terms of Mono?
From the documentation, I read that flatMap acts asynchronous and map synchronous. But that doesn't really make sense for me b/c Mono is all about parallelism and that point isn't understandable. Can someone rephrase it in a more understandable way?
Then in the documentation for flatMap stated (https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html#flatMap-java.util.function.Function-):
Transform the item emitted by this Mono asynchronously, returning the
value emitted by another Mono (possibly changing the value type).
Which another Mono is meant there?
Mono#flatMap takes a Function that transforms a value into another Mono. That Mono could represent some asynchronous processing, like an HTTP request.
On the other hand, Mono#map takes a Function that transforms a value of type T into another value, of type R. That transformation is thus done imperatively and synchronously (eg. transforming a String into an URL instance).
The other subtlety with flatMap is that the operator subscribes to the generated Mono, unlike what would happen if you passed the same Function to map.
I would say it simply,
map(a -> b) is returning Mono.just(b)
map wraps the returned value in another mono whereas flatmap already expects a Mono do no further wrapping required
Practical use case example,
public Mono<String> getResponseFromServer(Mono<String> request) {
// here few logics
request.flatMap(r -> callServer(r);
}
Where callServer looks like
public Mono<String> callServer(String body) {
// invoke http
return http call returned mono
}
Above use case is not possible with map.
Related
From its documentation, it states that Mono returns empty when it "completes without emitting any items". What does it mean to complete without emitting any items? Does it mean that it never sent any request or?
It depends on the implementation. Generally, for reactive data access libraries it means that the request/query was executed but yielded no results. However, this is not always the case as there are alternative behaviours like returning a default value or returning a Mono with error. Always consult the relevant library (e.g.: Spring Data) documentation to understand the behavior.
Answering from the perspective of "what does it mean in terms of behavior", not "what does the empty Mono behavior means in terms of business logic":
Mono is a Publisher, an interface that is defined to emit a set of signals to its Subscriber: onNext, onComplete, onError.
In the case of Mono the possible combinations are restricted:
onNext followed by onComplete (something was produced and we're done)
onError (something went wrong)
onComplete (nothing was produced but we're done)
The last one is the empty case you're wondering about: an empty Mono is one that never emits the onNext signal but rather simply emits onComplete.
To add to Simon's complete answer (why do I do that, hm?)
One typical use case of Mono returning empty is filtering. Think of it like if you need to do something in if then else style, in terms of Mono you could use .filter for then and .switchIfEmpty for else.
To understand the logic behind, for me it was also useful to look onto interface MonoSink<T> apidoc. It basically says the same: you can either complete without value, or with it, see two overloaded success methods.
The Gradle docs for lazy configuration states that in extension/DSL classes, properties like var someProperty = "default value" should actually be val someProperty: Property<String> = objectFactory.property(String::class.java).convention("default value"). This is to avoid unnecessary computation during the configuration phase;
I wonder if there is any downside in using plain types for simple values. The benefits are clear to me in case of computation or I/O, but if anything, for simple values I’d say a plain type would result in slightly less resource use during configuration (one less object created and no method calls).
The main reasons I prefer plain property types for simple values is simplicity and especially that the assignment operator can be used in a build script with Kotlin DSL, e.g. someProperty = "foo". I find this cleaner than someProperty.set("foo") and the latter is also imperative, while Gradle DSLs are otherwise mostly declarative.
It seems to work fine and in the task there would still be a Property<String> counterpart that can be initialized with someProperty.set(extension.someProperty), but since the documentation doesn’t mention it as a possibility for simple values, I’m wondering if there is a good reason for it that I couldn’t think of.
In addition to avoiding unnecessary computation during the configuration phase, using a property allows you to avoid race conditions with afterEvaluate clauses. Extension values set by build scripts are NOT available at configuration time.
Therefore, your example of task.someProperty.set(extension.somePlainField) will not work.
Using task.someProperty.set(extension.someProperty) (the method with signature set(value: Provider<T>)) makes sure that extension.someProperty.get() is not invoked until the task executes and reads its Property.
in order to achieve your goal of a fluent extension api, the recommended approach is to add a method to your extension such as
fun someProperty(value: String) {
someProperty.set(value)
}
then, build scripts can use it like:
myExtension {
someProperty("my value")
}
I use Spring boot reactive web flux for my rest endpoint.
What is the difference between :
#PostMapping
public Mono someMethod(#RequestBody SomeDTO someDto){
.....
to
#PostMapping
public Mono someMethod(#RequestBody Mono<SomeDTO> someDTO) {
....
I don't understand the difference in input argument to my controller method . I know one is pojo and the other in mono but what does it mean from reactive point of view?
First things, some background. You are using the 1.4. Annotated Controllers classes for WebFlux. These implementations are based on the 1.5. Functional Endpoints classes. I would recommend using the Functional Endpoints directly.
From a reactive POV you have to understand that you need to create the reactive flow. In the Mono method this has been created for you, in the SomeDTO method you should probably use Mono.just(someDTO) to create it.
What is important to understand in that statement is creation statements will be executed during the build phase not the execution phase of the reactive. The build phase is not executed asynchronously.
So, consider two mono creation statements.
return Mono.just(Thread.sleep(1000));
and
return Mono.just(1000).map(Thread::sleep);
Yes, I know it won't compile because of interrupted exception, but in the first case the Mono won't be returned to the client until 1 second and then it will do nothing when subscribed to. In the second case the mono will be returned to the client right away and will wait one second after it is subscribed to. The second one is what you are striving for.
What does it mean to you? Consider
return Mono.just(repo.save(someDto));
and
return someDto.map(repo::save);
In the first case, as above, someDto will be saved in the repo and then the mono will be returned to the client and will do nothing when subscribed to. Wrong! In the second case the mono will be returned to the client, the thread released back to the webflux framework for use in another request, and someDto will be saved when the client subscribes to the returned mono. What you are striving for.
Do it correctly with your first case by doing
return Mono.just(someDto).map(repo::save);
This is doing Mono.just(someDto) yourself whereas in your second case the webflux framework is doing it for you.
Which to choose? If you are just going to wrap someDto in a mono and use it then might as well have the framework do it for you or use the functional endpoints. If you are going to create a mono for some other reason and then use someDto during a mapping process use your first case. This second reason is, IMHO, a rare use case.
Typically when using the functional endpoints you will end up doing request.bodyToMono(SomeDto.class) which is equivalent to your second case and what is done by the framework for you in your second case.
Intellij has an inspection (i.e. lint check) that tells you functions that return Deferred should be named something ending in Async.
Naming conventions like these make sense to me in dynamically typed languages. But Kotlin has such a nice type-checker and ecosystem of tooling, so why rely on the convention?
Especially because Kotlin coroutines bake structured concurrency in, the function will probably also take a CoroutineScope parameter, which would serve the same visual cue at the call site:
suspend fun doStuff() = coroutineScope {
doStuffAsync(this /* CoroutineScope */).await()
//...
}
As a side note, I understand the inspection's message that you'd rarely want a function that returns a Deferred instead of a suspend function. That's not my question. My question assumes that you know what you're doing and you want a Deferred.
To begin with, a function should almost never return a Deferred that comes from an async block. It is up to the caller to wrap some unit of work into an async while doing other work in the foreground, then await on the async result before returning, and wrap all that code in a coroutineScope.
The intended source of Deferred instances is the adaptation layer between Kotlin coroutines and 3rd-party async APIs. For such calls it does make sense to put Async in the name and even some Java APIs follow this convention. For example, you may have a
fun fetchOrder(id: String): Deferred<Order>
and use it as
val orderCancelled = fetchOrder(orderId).isCancelled
This code is type-safe and type-correct, it doesn't cause any compiler errors. It looks like it's fetching an order from a remote system and then checking the order status (whether it's cancelled), but what it's actually doing is getting a Deferred<Order> and checking whether the Deferred is cancelled. Because your function name is missing Async, this kind of error is hard to spot.
Yes, you can also request the IDE to give you the return type, but it may take a while before you even suspect what's going on.
Deferred doesn't return the actual value but is "a light-weight non-blocking future that represents a promise to provide a result later".
As you cannot see this from method name, "we name such functions with the "...Async" suffix to highlight the fact that they only start asynchronous computation and one needs to use the resulting deferred value to get the result".
So the reader of your code can instantly see that your method is not returning the actual value but additionally has to call await() on it.
To your second point about the suspend function:
Usually it's other way round, the xyzAsync() function calls the suspend xyz() function.
As functions returning Deferred can be called from anywhere, not only from suspend functions.
In Alan Donovan and Brian Kernighan's "The Go programming language" book p333 (section 12.3 Display, a recursive value printer), it is mentioned that
Where possible, you should avoid exposing reflection in the API of a package. We'll define an unexported function display to do the real work of the recursion, and export Display, a simple wrapper around it that accepts an interface{} parameter.
func Display(name string, x interface{}) {
fmt.Printf("Display %s (%T):\n", name, x)
display(name, reflection.ValueOf(x))
And the display function prints different contents depending on the Kind of the input reflection value.
I have two questions
Why is it better to not expose the reflection in the package API?
Why is using an unexposed display function considered as not exposing reflection in the API? Don't we still call reflection.ValueOf() in Display?
I guess I don't know the definition of "exposing reflection in the package API". Does it just refer to the function arguments or both arguments and content? If it's the former case, then there seems no need to define display since the signature of Display is x interface{}. If it's the latter case, why is it better?
In the book's example
In the book's example, it is because the usage of reflection is an implementation detail. You should always try to hide the implementation details, so you may change the implementation at any time without breaking the "public" API of the package. If you export / add something to the API of your package, you have to carry that for the rest of your life (given you don't want to make backward-incompatible API changes, which is really bad in general).
In general
"interface{} says nothing" – Rob Pike. Given that, reflect.Value says even less. Unless you have a good reason (can't think of any outside of the reflect package itself), you shouldn't create public functions that expect reflect.Value as their arguments.
Even if you have a "general" function that must take a value of any type, interface{} is preferred as then at least the clients can pass what they have as-is, without having to wrap them in reflect.Value.