48

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);
}
ryanwebjackson
  • 1,017
  • 6
  • 22
  • 36
nanosoft
  • 2,913
  • 4
  • 41
  • 61

7 Answers7

61

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.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
11

According to the doc you can do:

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

be aware of the blocking call

ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
  • 3
    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? – nanosoft Nov 08 '17 at 12:56
9

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

public void getValue(Mono<String> monoString)
{
   monoString.flatMap(this::print);
}
AjCodez
  • 360
  • 3
  • 10
nanosoft
  • 2,913
  • 4
  • 41
  • 61
  • 8
    Just an FYI, instead of creating your own `print(String str)` method and doing `this::print`, you can simply do `System.out::print` – AjCodez Mar 22 '18 at 17:03
  • Why does this exact piece of code gives me an error: "Cannot infer type argument(s) for flatMap(Function super T,? extends Mono extends R>>)" ?? – Ray Zhang Jun 13 '19 at 04:11
  • This gives me the error [here](https://stackoverflow.com/questions/66492668/to-take-a-string-from-a-fluxstring-throws-type-mismatch-cannot-convert-from-d) – rupweb Mar 05 '21 at 12:52
  • 1
    does this answer provide any extra information other than Alexey Romanov's? – Lei Yang Apr 28 '21 at 07:52
3

What worked for me was the following:

monoString.subscribe(this::print);

AjCodez
  • 360
  • 3
  • 10
3

Simplest answer is:

 String returnVal = mono.block();
KayV
  • 12,987
  • 11
  • 98
  • 148
1

This should work

String str = monoString.toProcessor().block();
Vijay
  • 558
  • 6
  • 22
0

Better

monoUser.map(User::getId) 
Armen Arzumanyan
  • 1,939
  • 3
  • 30
  • 56
  • 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](https://stackoverflow.com/help/how-to-answer) very helpful. Please edit your answer - [From Review](https://stackoverflow.com/review/low-quality-posts/21564390) – Nick Dec 01 '18 at 05:08
  • 2
    What's User, monoUser and getId? None of them are in original question. So all you are trying is to solve an hypothetical query. – nanosoft Dec 03 '18 at 09:46
  • This will return a Mono back with the value of the ID --> Mono if the id is Integer. I think the question was to return a String and not a Mono – Ahmed Aziz Oct 06 '21 at 13:34