13

I have a Mono<String> object in reactor. How can I get a string value from this object?

I know I can do something like below : For Mono<String> userName, I can do,

userName.map(System.out::println). 

But this will directly print the value. I want to store this string value into another variable so that I can pass that variable around to some other functions. How can I extract this value?

Rohan Gujarathi
  • 133
  • 1
  • 1
  • 4

2 Answers2

15

To answer the question directly in its simplest form - you use Mono.block().

But you almost certainly shouldn't, as this blocks the thread, defeating the point of using reactor in the first place. You should, instead, call subscribe() and then provide a consumer. The consumer will be called asynchronously when the Mono emits a value, with that value as a parameter.

There's nothing inherently stopping you just assigning the value to a field of course:

mono.subscribe(v -> this.value = v);

...but this has very limited usefulness in practice, since you won't know when that field will be initialised.

The more normal way is to either call the other methods in your subscriber all in one go:

mono.subscribe(v -> {
    oneMethodThatNeedsTheValue(v);
    anotherMethodThatNeedsTheValue(v);
});

...or to use Mono.cache() and pass it around:

class Test {

    void useMonoVal(Mono<String> mono) {
        mono.subscribe(s -> System.out.println("I need to see " + s));
    }

    void anotherMethod(Mono<String> mono) {
        mono.subscribe(s -> System.out.println("I need to talk to " + s));
    }

    public static void main(String[] args) {
        Mono myMono = Mono.just("Bob").cache();
        Test t = new Test();
        t.useMonoVal(myMono);
        t.anotherMethod(myMono);
    }

}

(The cache() method ensures that the Mono is only evluated once and then cached for all future subscribers, which is irrelevant when using the just() factory of course, but just there for the sake of a complete example.)

To expand, the whole point of using a reactive paradigm (and therefore reactor, and by extension its Mono and Flux objects) is that it enables you to code in a non-blocking way, meaning that the current thread of execution isn't "held up" waiting for the mono to emit a value.

Side note: I'm not sure it's directly relevant to the question, but you can't do a.map(System.out::println); - you probably mean a.subscribe(System.out::println);.

Michael Berry
  • 70,193
  • 21
  • 157
  • 216
0

You have to subscribe before getting the string from mono object

Just have a look at this for more detail How to get String from Mono<String> in reactive java

public class MonoT {
        static String x = null;
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Mono<String> username = Mono.just("Naren");
            
            username.subscribe(v->{
                x = v;
            }); 
            
            System.out.println(x);
        }
    
    }
rupweb
  • 3,052
  • 1
  • 30
  • 57
Narandhran Thangavel
  • 1,392
  • 1
  • 12
  • 20
  • Thanks for this solution. This will work, but is it the only way to get values from Mono? Is it possible to get value directly in a local variable instead of creating a class level static variable. I want to use this type of code at production level and creating static variables for every mono object does not sound like a good solution – Rohan Gujarathi Aug 05 '19 at 08:10
  • I think other way is to use block(). But even that is not a good solution – Rohan Gujarathi Aug 05 '19 at 08:18
  • block() ll return the value it holds. When you calling it, it ll block the current thread. Then your program wouldn't reactive. You shouldn't use that. You have to use it in a non-blocking way only – Narandhran Thangavel Aug 05 '19 at 08:24