'WebClient synchronous call does not return from within a filter stack trace

In a Spring Gateway API I have a filter which calls a class to make a call to another API using WebClient. If I make the same call from say a controller the call returns. However when this webclient call is made from within the Filter stack it never returns. I am trying to make this call synchronously. I cannot use the block() method because Reactive classes error.

Here is the method in question:

public void doPost() {
              ApiResponse<Void> response =  webClientBuilder.build().post()
              .uri("http://localhost:8080")
              .retrieve()
              .bodyToMono(new ParameterizedTypeReference<ApiResponse<Void>>() {})
              .block();
}

I am very new to WebClient and need someone to tell me how I can synchronously make this call. I have tried another variation which is toFuture().get() instead of the last line but this also does not return.

It get the below error:

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

My mistake it is an authentication filter that this is being run from:

public class AuthServiceAuthenticationManager implements ReactiveAuthenticationManager {
        
        private final MyClient myClient;
        
        @Override
        public Mono<Authentication> authenticate(Authentication authentication) {
            
           //Below line does not return using my webclient
            myClient.post();
            
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), new ArrayList<GrantedAuthority>());
            return Mono.just(token);
        }
    }


Solution 1:[1]

As I mentioned in comment, the reason is simple - you and blocking doPost is called from the reactive flow. WebClient is a non-blocking client and as you are using it from the ReactiveAuthenticationManager you could keep the whole flow reactive.

Solution:

  1. Remove block() from the doPost and return Mono.
public Mono<ApiResponse<Void>> doPost() {
    return webClientBuilder.build().post()
            .uri("http://localhost:8080")
            .retrieve()
            .bodyToMono(new ParameterizedTypeReference<ApiResponse<Void>>() {})
}
  1. Construct reactive flow in AuthServiceAuthenticationManager. Logic of authenticate is not really clear but based on your example it could look like
public Mono<Authentication> authenticate(Authentication authentication) {
    UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), new ArrayList<>());
    return doPost()
            .thenReturn(token);
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alex