简体   繁体   中英

Spring Webclient is not calling another service

I am trying call another service from my Spring Cloud Gateway service.

In the AuthenticationServiceClient the Webclient supposed to call the desired service, But it does not.

I can not find what I am doing wrong.

This is the implementation of AuthenticationServiceClient.class :

public class AuthenticationServiceClientImpl implements AuthenticationServiceClient {

private final WebClient webClient;

@Autowired
public AuthenticationServiceClientImpl(WebClient.Builder builder) {

    this.webClient = builder.baseUrl("http://localhost:9002").build();
}

@Override
public Mono<AppUser> getAppUser(String accessToken) {

    return this.webClient.get().uri
                    (uriBuilder ->
                            uriBuilder
                                    .path("/api/authentication-service/get-user-detail")
                                    .queryParam("accessToken", accessToken)
                                    .build()
                    )
            .accept(MediaType.APPLICATION_JSON)
            .retrieve()
            .onStatus(HttpStatus::isError, error -> Mono.just(new RuntimeException("Error from AUTHENTICATION SERVICE")))
            .bodyToMono(AppUser.class);
}

}

This is AuthenticationFilter.class :

public class AuthenticationFilter implements GatewayFilter {

private final AuthenticationServiceClient authClient;

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

    ServerHttpRequest request = exchange.getRequest();

    final String token = this.getAuthHeader(request);

    authClient.getAppUser(token).flatMap(response -> {
        System.out.println(response);
        this.populateRequestWithHeaders(exchange, response);
        return chain.filter(exchange);
    });

    return this.onError(exchange, "Authorization header is invalid", HttpStatus.UNAUTHORIZED);
}
}

some codes and annotations are omitted for brevity.

Your problem is here:

// You are ignoring the return and breaking the chain
authClient.getAppUser(token).flatMap(response -> {
        System.out.println(response);
        this.populateRequestWithHeaders(exchange, response);
        return chain.filter(exchange);
    });

You need to handle the returning Mono so that the framework can subscribe to it.

return authClient.getAppUser( ... )

this line:

return this.onError(exchange, "Authorization header is invalid", HttpStatus.UNAUTHORIZED);

should be completely removed. If you want to handle errors you should use an error operator

return authClient.getAppUser( ... ).onErrorResume( ... ) // one of many error operators

The problem is that you are thinking imperatively when programming. You are continuing the filter chain in the flatMap but none of that will get called because you have broken the return chain.

spring reactor will when someone calls your service, first call your operators upstream to build the chain of operators (this is called the assembly phase) up until it finds a producer of data. Then it will start calling the operators downstream to start producing data to the calling client.

But you broke that chain and thats why your rest call was not called.

I suggest you go through the getting started section of the reactor official documentation, as this is basic knowledge when working with reactive programming.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM