1

Related to this question to take a string from a Mono I think I have finally got how to take a String out of a Flux<String> like this:

Flux<String> rates = controller.getRate(json);          
String myRate = rates.next().subscribe(System.out::print);

However, this is causing a type mismatch cannot convert from Disposable to String

enter image description here

What am I getting wrong?

To clarify, it's for testing - I need an internal String value. So if I have a Flux<String> of strings: one, two, three then I want to set another String to value one

String s = ...

If I try

String s = rates.doOnNext(System.out::print);

Then I get a type mismatch: cannot convert from Flux<String> to String

enter image description here

If I try

String s = next().flatMap(System.out::print);

Then I get a type mismatch: cannot convert from Mono<Object> to String

enter image description here

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
rupweb
  • 3,052
  • 1
  • 30
  • 57

1 Answers1

2

What am I getting wrong?

It's not clear what you're trying to achieve, but potentially a few things here:

  • A Flux<String> returns a stream of 0..n strings, do you definitely only ever want the first one it returns (which is what next() does?)
  • You've realistically got two options in getting a value from a publisher - you can do it asynchronously by using the reactive chain, or you can block the thread until it completes, then get it directly. (Note that if you block though, you're losing all the advantages the reactive framework gives you, so it's rare that this is actually what you want to do.) In this example it looks like you're subscribing, but also trying to block, which doesn't make any sense - you need to pick one or the other.
  • If you don't want to block and you're using a reactive framework like webflux, then subscribing is generally the framework's job anyway - you would just pass your reactive calls up the chain until you eventually returned a Mono or a Flux on (for example) your controller method. (Subscribing is only really valid if you're not using a framework, and managing the entirety of the reactive chain + event loop yourself.)
  • If you don't want to block but want to make sure the value is printed out as soon as it's emitted (known as a side-effect) then you can use the doOnNext(System.out::print) as part of the reactive chain to achieve this.
Michael Berry
  • 70,193
  • 21
  • 157
  • 216
  • Thank you - all i want to do is assign the String value of the `next()` in the Flux to another String variable. No blocking! – rupweb Mar 05 '21 at 14:54
  • Per update if I try `doOnNext(System.out::print)` then I get a type mismatch. – rupweb Mar 05 '21 at 15:03
  • 1
    @rupweb You *can't* assign the value to a "normal" String variable without blocking - this is where you're likely coming unstuck. You have to use it, and do whatever you want with it, as part of the reactive chain. The moment you try to assign it elsewhere and wait for the result to complete, you're blocking (by definition.) – Michael Berry Mar 05 '21 at 15:57
  • THANKS... `String s = rates.doOnNext(System.out::print).blockFirst();` is working for the test purpose although i would prefer to find a string value through a `subscribe`. Maybe [this](https://stackoverflow.com/questions/34332842/how-to-return-a-value-from-a-lambda-expression) could be a way to do it? – rupweb Mar 05 '21 at 16:06
  • 1
    The approach there is just getting a future and then calling `get()` - which is just blocking by a different name. You can subscribe and then assign to a field in your subscriber - but that's of limited usefulness in most situations since you won't know when the value has been updated. – Michael Berry Mar 05 '21 at 18:38