How to get String from Mono<String> in reactive java
Asked Answered
T

7

55

I have a method which accepts Mono as a param. All I want is to get the actual String from it. Googled but didn't find answer except calling block() over Mono object but it will make a blocking call so want to avoid using block(). Please suggest other way if possible. The reason why I need this String is because inside this method I need to call another method say print() with the actual String value. I understand this is easy but I am new to reactive programming.

Code:

public String getValue(Mono<String> monoString) {
    // How to get actual String from param monoString
    // and call print(String) method
}

public void print(String str) {
    System.out.println(str);
}
Terresaterrestrial answered 8/11, 2017 at 12:37 Comment(3)
could you explain to me what Mono is?Crispa
check -> musigma.org/java/2016/11/21/reactor.htmlTerresaterrestrial
If you use the block(Duration timeout) with zero duration - projectreactor.io/docs/core/release/api/reactor/core/publisher/…Cicerone
T
9

Finally what worked for me is calling flatMap method like below:

public void getValue(Mono<String> monoString)
{
   monoString.flatMap(this::print);
}
Terresaterrestrial answered 9/11, 2017 at 4:52 Comment(4)
Just an FYI, instead of creating your own print(String str) method and doing this::print, you can simply do System.out::printLimpopo
Why does this exact piece of code gives me an error: "Cannot infer type argument(s) for <R> flatMap(Function<? super T,? extends Mono<? extends R>>)" ??Metamorphose
This gives me the error hereCucumber
does this answer provide any extra information other than Alexey Romanov's?Emblazonry
B
64

Getting a String from a Mono<String> without a blocking call isn't easy, it's impossible. By definition. If the String isn't available yet (which Mono<String> allows), you can't get it except by waiting until it comes in and that's exactly what blocking is.

Instead of "getting a String" you subscribe to the Mono and the Subscriber you pass will get the String when it becomes available (maybe immediately). E.g.

myMono.subscribe(
  value -> System.out.println(value), 
  error -> error.printStackTrace(), 
  () -> System.out.println("completed without a value")
)

will print the value or error produced by myMono (type of value is String, type of error is Throwable). At https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html you can see other variants of subscribe too.

Bloch answered 8/11, 2017 at 13:9 Comment(6)
That's what I am looking for-> how to subscribe it? May be via lambda?Terresaterrestrial
Yes, that's one option. See the edit. But the point is that you can't write getValue method in your question.Bloch
Actually with string value I need to call another method... Let's say Mono<string> myMono has "abc" as actual string. With that String I need to call another method say print(String str) in that method. So how do I achieve it.. myMono.subscribe(value->print(value)) ?Terresaterrestrial
Yes, just as I show with Console.out.println in the example.Bloch
What is Console.out.println? Shouldn't it be System.out.println?Cepheus
@Cepheus Yes, not sure what I confused it with.Bloch
A
14

According to the doc you can do:

String getValue(Mono<String> mono) {
    return mono.block();
}

be aware of the blocking call

Alleviative answered 8/11, 2017 at 12:44 Comment(1)
I know usage of block but as it will make a blocking call I don't want to use it. Isn't there another way?Terresaterrestrial
T
9

Finally what worked for me is calling flatMap method like below:

public void getValue(Mono<String> monoString)
{
   monoString.flatMap(this::print);
}
Terresaterrestrial answered 9/11, 2017 at 4:52 Comment(4)
Just an FYI, instead of creating your own print(String str) method and doing this::print, you can simply do System.out::printLimpopo
Why does this exact piece of code gives me an error: "Cannot infer type argument(s) for <R> flatMap(Function<? super T,? extends Mono<? extends R>>)" ??Metamorphose
This gives me the error hereCucumber
does this answer provide any extra information other than Alexey Romanov's?Emblazonry
L
3

What worked for me was the following:

monoString.subscribe(this::print);

Limpopo answered 22/3, 2018 at 17:1 Comment(0)
P
3

Simplest answer is:

 String returnVal = mono.block();
Premonitory answered 2/6, 2020 at 16:48 Comment(1)
But it blocks the callItinerant
L
1

This should work

String str = monoString.toProcessor().block();
Ludovick answered 1/3, 2021 at 18:53 Comment(1)
I think this is now deprecatedWhang
S
-1

Better

monoUser.map(User::getId) 
Sarto answered 30/11, 2018 at 19:46 Comment(3)
While this might answer the authors question, it lacks some explaining words and/or links to documentation. Raw code snippets are not very helpful without some phrases around them. You may also find how to write a good answer very helpful. Please edit your answer - From ReviewDropline
What's User, monoUser and getId? None of them are in original question. So all you are trying is to solve an hypothetical query.Terresaterrestrial
This will return a Mono back with the value of the ID --> Mono<Integer> if the id is Integer. I think the question was to return a String and not a MonoAnodic

© 2022 - 2024 — McMap. All rights reserved.