I\'m probably missing something but I can\'t figure out what it is.
The following code does nothing at all:
webClient.get().uri(\"/some/path/here\").ret
Short Answer
subscribe
does not block current thread, that means app main thread can complete earlier than Flux emits any element. So either use block
or employ waiting in the main thread.
Details
Call to the no-args subscribe() just makes request(unbounded)
on Flux
without setting up any Subscriber
. It triggers operation generally in a separate thread but does not block the current thread. Most likely, your main thread ends before WebClient
received the response in that separate thread and passive side effect doOnNext(...) happened.
To illustrate/test that operation is started, wait for some time in the main thread. Just put the following line right after subscribe()
call:
Thread.sleep(1000);
Now, after playing with the timeout value, you'll be able to see result printed.
Let's now implicitly ship a custom Scheduler
for async operations and wait for all its tasks to be completed. Also, let's pass the System.out::println
as subscribe(...)
argument instead of doOnNext
, so that complete code appears as follows:
ExecutorService executor = Executors.newSingleThreadExecutor();
webClient.get().uri("/some/path/here").retrieve()
.bodyToMono(GetLocationsResponse.class)
.publishOn(Schedulers.fromExecutor(executor)) // next operation will go to this executor
.subscribe(System.out::println); //still non-blocking
executor.awaitTermination(1, TimeUnit.SECONDS); //block current main thread
This example uses slightly different subscribe(Consumer). Most importantly, it adds publishOn(Scheduler) which is backed by ExecutorService
. The latter is used then to wait for termination in the main thread.
Surely, the much easier way to achieve the same result is to use block()
as you mentioned initially:
webClient.get().uri("/some/path/here").retrieve() .bodyToMono(GetLocationsResponse.class) .doOnNext(System.out::println) .block();
Finally, note on your third example with Flux.just(...)...subscribe()
- seems it just quickly completes before your main thread gets terminated. That's because it requires way less time to emit a few String
elements compared to the emission of a single GetLocationsResponse
element (implying timings for write request+read response+parse into POJO). However, if you make this Flux
to delay elements, you'll get the same behavior reproduced:
Flux.just("1", "2", "3")
.filter(s -> !s.equals("2"))
.delayElements(Duration.ofMillis(500)) //this makes it stop printing in main thread
.doOnNext(System.out::println)
.subscribe();
Flux.just("1", "2", "3")
.filter(s -> !s.equals("2"))
.delayElements(Duration.ofMillis(500))
.doOnNext(System.out::println)
.blockLast(); //and that makes it printing back again