2

I would like to make this call and return a string but I'm having this error:

"java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-3"

I dont understand why am I doing wrong? WebClient supports asynchronous as well as synchronous calls.

This a springboot project with just 3 dependencies.

How can I return just a string like a normal synchronous call?

@RestController
public class HomeController {

@GetMapping("/")
public String home() {
String resp = webclient.get()                             
                       .uri(ANY_URL).retrieve()
                       .bodyToMono(String.class)
                       .block();
return resp;

 }


}

pom.xml
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

Thanks.

Andres
  • 731
  • 2
  • 10
  • 22
  • Does this answer your question? [block()/blockFirst()/blockLast() are blocking error when calling bodyToMono AFTER exchange()](https://stackoverflow.com/questions/51449889/block-blockfirst-blocklast-are-blocking-error-when-calling-bodytomono-afte) – Michał Krzywański Oct 22 '22 at 15:41
  • 1
    To make it work asynchronously/error vanish: you have to add `spring-boot-starter-web` (dependency), i suppose. – xerx593 Oct 22 '22 at 15:54
  • ..to keep it reactive, just: return `Mono` (without "blocking") – xerx593 Oct 22 '22 at 15:55
  • It worked by adding spring-boot-starter-web, do you know why it was needed? @xerx593 – Andres Oct 22 '22 at 16:18
  • 1
    In short: This adds "servlet/filters", which "support blocking" ... – xerx593 Oct 22 '22 at 16:24

2 Answers2

0

Fixed by adding spring-boot-starter-web

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
Andres
  • 731
  • 2
  • 10
  • 22
0

Not sure what is your goal but the whole idea of Webflux is to create non-blocking reactive services. WebClient support both async and sync usage but the error you are getting is from reactive controller. There is no reason to block in your example - just change return type from String to Mono<String>.

@GetMapping("/")
public Mono<String> home() {
String resp = webclient.get()                             
       .uri(ANY_URL).retrieve()
       .bodyToMono(String.class);
 }

The intuition behind this is

  • use spring-boot-starter-webflux and WebClient in async mode to create reactive services. Controller should return Mono or Flux. The caveat here is that your logic should be reactive (async) end-to-end to get full advantage of the Reactive API.
  • add spring-boot-starter-web if you want to build non-reactive service and just use WebClient in sync (blocking) mode as your Http client.
Alex
  • 4,987
  • 1
  • 8
  • 26