I want cast to mono from flux. However, I can't decide when to use single() or next() and don't know which one is more effective?
Flux<String> optionalIdsFlux = Flux
.fromIterable(result.getPersonalizationEntity())
.filter(i -> i.getKey().equals(PERSONALIZATION_KEY))
.next() // or single() ??
.map(DataEntity::getValue)
.flatMapMany(Flux::fromIterable);`
They are actually quite different. next() takes the first value that is emitted and cancels the subscription afterwards.
single(), on the other hand, expects that exactly one element is emitted in the first place. If that's not the case, and zero or more elements are emitted, then an error signal is emitted.
Which one to choose depends on your use case. If the source is guaranteed to emit exactly one element, then you can use single(). Otherwise use next().
Additionally to what a better oliver said, if there is a super strong guarantee that the Publisher you have only ever emits at most one onNext, you can turn it into a Mono - without the safety belt on - by using Mono.fromDirect(Publisher).
Related
I'm wondering if it is possible to put the value of a Mono as a value into a Flux just like you could append any object to a list. I know there are some methods you could use but none of them fulfills my exact purpose. What I tried so far:
Flux<T> flux;
Mono<T> mono;
Flux.merge(flux, mono); // <- returns Flux<Object>
This doesn't sound too bad but notice that it does not return Flux<T> as I would need it but Flux<Object>. Same with Flux.concat(flux, mono);. The method Flux.zip(flux, mono); would stop merging as soon as the Mono completes as far as I understand.
Has somebody a solution for this?
This is what I ended up doing:
I have the method return a Flux of the desired type which in my case was an 'ExtendedResourceModel'. I create a Mono of this type which gets initialized by another method that I commented out to keep this answer as concise as possible. If a certain condition is met I want to also use a Flux from a different source so I use 'Flux.concat()' to put all elements into a single Flux. The 'concat'-method works by subscribing to the first argument, letting it finish, subscribing to the second one and so on.
In case of my condition not being met I just use 'concat' again but this time with only the Mono which will put the Mono's element into a new Flux. This way both cases have the same return type.
It is not possible to do, if you need to do that you can convert your Flux to mono
Mono monoToFlux = flux.collectList();
Mono mono;
Mono.zip (mono, monoToFlux).flatmap(tuple -> {
... more code ...
})
I'm looking at some code where .flatMap was called on a Mono - I've gone through some of the PR discussions on Rx GitHubs about adding such functionality, but I don't really understand why someone would do that: flatMap, to me, seems inherently purposed for applying a function to 1...n elements. Applying a function to 0...1 elements can be done with a single function call.
You can use .map() as long as it is non-blocking.
Otherwise, your inner transformation will return Mono that will complete in future (e.g. a network call), and you should subscribe on it with .flatMap instead of blocking the processing.
flatMap works with any Publisher<T> and works with any 0..n where n can also be 0.
If you need to transform one element into a few (e.g. split a String) then you can use flatMapIterable, it has lower overhead than flatMap.
I hope my question is clear enough.
Let's say your have an API that performs requests over a network backed by IO-streams (input and output).
Using RxJava (which I am debuting with), I would think it could be possible to do the following:
public Single<MyData> getMyDataFromApi() {
return requestMyData()
.map/flat/then()->waitAndprocessData() // here is the missing link for me. What can I use ?
.andThen()->returnData()
As you will understand, the method requestMyData returns a Completable which sole responsibility and only task it to perform said request (IO-type operation).
Then, upon performing the request, the remote entity shall process it and return a result the requested MyData object by performing an IO-type operation as well.
The key-point here, is that I work with streams (both input and output) which reading and writing operations are obviously performed in separate IO threads (using Schedulers.io()).
So in the end, is there a way so that my getMyDataFromApi() method does the following :
Perform the request -> it's a completable
Wait for the result -> something like a subscribe ? but without splitting the chain
Process the result -> it's a single or can be a lambada in map method
Return the result -> final element, obviously a single
To conclude, I strongly believe that requestMyData's signature should be that of a Single, because it's getter and I am expecting a result or an error.
Without having the implementation of the methods is quite hard to understand the real problem.
If requestMyData returns a Completable and waitAndprocessData a Single, you can do the following:
return requestMyData().andThen(waitAndprocessData());
Anyway remember that a Completable is computation without any value but only indication for completion (or exceptions).
What is the use case for Mono<T> and Flux<T> as parameter in function.
Code
Flux<String> findByLastName(Mono<String> lastname) {
//implementation
}
When I invoke above method from rest, what will be difference from not using String.class as parameter?
To answer your first comment question:
#ErwinBolwidt i know use case for Mono/Flux in computation but i dont understand specifically using it as method parameter – Bibek Shakya
When you use it as a parameter you have to deal with it as a stream (meaning you don't have it yet) so for example you should never say lastname.block(), because this means you've just blocked the thread until this value is available.
Disclaimer Extra information
If you're asking whether you should wrap anything from now on in a Mono or a flux, then of course not, because it adds unnecessary complexity to the method and the caller.
And for a design perspective, answer is simple, by asking basic questions:
When to use a Mono in general ?
Well, when you still don't have the value.
When to use Flux in general ?
Well, when you have a stream of data coming or not.
So we should not think of who is using the method and try to make the method convenient for him, but actually we should think of the method needs.
And a use case for that is when the method actually needs argument in this way; meaning you actually do stream processing inside, for example your method accepts an infinite stream of sensor data, and the method inside is going crazy like:
Flux<Point> processSensor(Flux<Double> data){
return data.filter(blabla).zipWith(blabla).map(...);
}
Only use cases I can think of why a method parameter is Mono<String> lastname
Was retrieved from a WebClient/Router type function
#Secured("ROLE_EVERYONE") was used in a previous method to retrieve the lastname
For this to work the return type of the method must be a
org.reactivestreams.Publisher (i.e. Mono/Flux).
I have a need in a block of code to consume 'n' items from a stream then finish, in essence:
public static <T> void eat(Stream<T> stream, int n)
// consume n items of the stream (and throw them away)
}
In my situation, I can't change the signature to return Stream<T> and simply return stream.skip(n); I have to actually throw away some elements from the stream (not simple logic) - to be ready for a down stream consumer which doesn't need to know how, or even that, this has happened.
The simplest way to do this is to use limit(n), but I have to call a stream terminating method to activate the stream, so in essence I have:
public static <T> void skip(Stream<T> stream, int n) {
stream.limit(n).forEach(t -> {});
}
Note: This code is a gross over simplification of the actual code and is for illustrative purposes only. Actually, limit won't work because there is logic around what/how to consume elements. Think of it like consuming "header" elements from a stream, then having a consumer consume the "body" elements.
This question is about the "do nothing" lambda t -> {}.
Is there a "do nothing" consumer somewhere in the JDK, like the "do nothing" function Function.identity()?
No, JDK does not provide dummy consumer as well as other predefined functions like dummy runnable, always-true predicate or supplier which always returns zero. Just write t -> {}, it's anyways shorter than calling any possible ready method which will do the same.
Introducing the dummy (empty) consumer was considered in the scope of the ticket:
[JDK-8182978] Add default empty consumer - Java Bug System.
Archived: [JDK-8182978] Add default empty consumer - Java Bug System.
According to the ticket, it was decided not to introduce it.
Therefore, there is no dummy (empty) consumer in the JDK.
Yes. Well, more or less yes...
Since a Function is also a Consumer, you can use Function.identity() as a "do nothing" Consumer.
However, the compiler needs a little help to make the leap:
someStream.forEach(identity()::apply);