2

I am using Spring WebClient to call an internal API but sometime my webClient doesn't analyse the response code and stay block on "exchangeToMono" method and waiting .

I use :

  • spring-boot-starter-parent 2.5.2
  • spring webclient 5.3.8

I migrate to spring-boot-starter-parent 2.5.2. Before I used exchange but it is now deprecated and I thought that was my problem

A solution I didn't try is to use OpenFeign

My webclient config :

Builder builder = WebClient.builder()
                .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(16 * 1024 * 1024))
                //.exchangeStrategies(strategies)
                .clientConnector(httpProxyClientConnector(baseUrl))
                .baseUrl(baseUrl)
                .filter(filter)
                .filter(new LoggingExchangeFilterFunction());
        if (apiKey.isPresent()) {
            builder = builder.defaultHeader(X_API_KEY, apiKey.get());
        }
        return builder
                .defaultHeader(ACCEPT, APPLICATION_JSON_VALUE)
                .defaultHeader(CONTENT_TYPE, APPLICATION_JSON_VALUE) // all exchanges are JSON
                .build();

httpProxyClientConnectorMethod :

new ReactorClientHttpConnector(
                    HttpClient.create()
                            .compress(true)
                            .wiretap(true)
                            .proxy(typeSpec ->
                                            typeSpec
                                                    .type(HTTP)
                                                    .host(httpProxyHost)
                                                    .port(httpProxyPort)));

Webclient call :

WebClient.get()
                .uri(uriBuilder ->
                        {
                            UriBuilder uri = uriBuilder.path("/v2/period").queryParam("from", from.format(FLATTENED_DATE_FORMAT))

                            return uri.build();
                        }
                )
                .exchangeToMono(clientResponse -> {
                    HttpStatus status = clientResponse.statusCode();
                    //Retry as response is being processed by api
                    if (ACCEPTED.equals(status)) {
                        return Mono.error(new EnqueuedRequest());
                    }
                    if (ApiFallbackUtils.getAllErrorStatus().contains(status)) {
                        return Mono.error(ApiFallbackUtils.getException(status));
                    }
                    if(status.equals(NO_CONTENT)){
                        Mono.just(emptyList());
                    }
                    return clientResponse.bodyToMono(DateKpi.class);
                })
                .retryWhen(Retry.fixedDelay(retryValue, ofMillis(delayValue)).filter(e -> e instanceof EnqueuedRequest))
                .onErrorResume(throwable -> ApiFallbackUtils.returnFallback(new DateKpi(), throwable));

Log with error:

[reactor-http-nio-4] [DEBUG] 2021-07-02 17:15:12.350 io.netty.util.internal.logging.Log4J2Logger: [id:e80c6acf-2, L:64171 - R:proxy-internet.org:3128] READ: 913B
         +-------------------------------------------------+
         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 48 54 54 50 2f 31 2e 31 20 32 30 34 20 0d 0a 44 |HTTP/1.1 204 ..D|
|00000010| 61 74 65 3a 20 46 72 69 2c 20 30 32 20 4a 75 6c |ate: Fri, 02 Jul|
|00000020| 20 32 30 32 31 20 31 35 3a 31 35 3a 31 32 20 47 | 2021 15:15:12 G|
|00000030| 4d 54 0d 0a 53 65 72 76 65 72 3a 20 41 70 61 63 |MT..Server: Apac|
|00000040| 68 65 0d 0a 58 2d 43 6f 72 72 65 6c 61 74 69 6f |he..X-Correlatio|
|00000050| 6e 2d 49 64 3a 20 33 63 37 39 38 35 63 63 2d 63 |n-Id: 3c7985cc-c|
|00000060| 35 34 61 2d 34 33 35 32 2d 62 39 38 35 2d 63 63 |54a-4352-b985-cc|
|00000070| 63 35 34 61 33 33 35 32 39 39 0d 0a 58 2d 52 65 |c54a335299..X-Re|
|00000080| 71 75 65 73 74 2d 49 64 3a 20 33 63 37 39 38 35 |quest-Id: 3c7985|
|00000090| 63 63 2d 63 35 34 61 2d 34 33 35 32 2d 62 39 38 |cc-c54a-4352-b98|
|000000a0| 35 2d 63 63 63 35 34 61 33 33 35 32 39 39 0d 0a |5-ccc54a335299..|
|000000b0| 43 61 63 68 65 2d 43 6f 6e 74 72 6f 6c 3a 20 6e |Cache-Control: n|
|000000c0| 6f 2d 63 61 63 68 65 2c 20 6e 6f 2d 73 74 6f 72 |o-cache, no-stor|
|000000d0| 65 2c 20 6d 61 78 2d 61 67 65 3d 30 2c 20 6d 75 |e, max-age=0, mu|
|000000e0| 73 74 2d 72 65 76 61 6c 69 64 61 74 65 0d 0a 43 |st-revalidate..C|
|000000f0| 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 61 70 70 |ontent-Type: app|
|00000100| 6c 69 63 61 74 69 6f 6e 2f 6a 73 6f 6e 3b 63 68 |lication/json;ch|
|00000110| 61 72 73 65 74 3d 55 54 46 2d 38 0d 0a 45 78 70 |arset=UTF-8..Exp|
|00000120| 69 72 65 73 3a 20 30 0d 0a 50 72 61 67 6d 61 3a |ires: 0..Pragma:|
|00000130| 20 6e 6f 2d 63 61 63 68 65 0d 0a 58 2d 43 6f 6e | no-cache..X-Con|
|00000140| 74 65 6e 74 2d 54 79 70 65 2d 4f 70 74 69 6f 6e |tent-Type-Option|
|00000150| 73 3a 20 6e 6f 73 6e 69 66 66 0d 0a 58 2d 46 72 |s: nosniff..X-Fr|
|00000160| 61 6d 65 2d 4f 70 74 69 6f 6e 73 3a 20 44 45 4e |ame-Options: DEN|
|00000170| 59 0d 0a 58 2d 58 53 53 2d 50 72 6f 74 65 63 74 |Y..X-XSS-Protect|
|00000180| 69 6f 6e 3a 20 31 3b 20 6d 6f 64 65 3d 62 6c 6f |ion: 1; mode=blo|
|00000190| 63 6b 0d 0a 56 69 61 3a 20 31 2e 31 20 61 70 69 |ck..Via: 1.1 api|
|000001a0| 2e 64 65 63 61 74 68 6c 6f 6e 2e 6e 65 74 2c 20 |.test.net, |
|000001b0| 31 2e 31 20 67 6f 6f 67 6c 65 0d 0a 41 6c 74 2d |1.1 google..Alt-|
|000001c0| 53 76 63 3a 20 63 6c 65 61 72 0d 0a 53 65 74 2d |Svc: clear..Set-|
|000001d0| 43 6f 6f 6b 69 65 3a 20 76 69 73 69 64 5f 69 6e |Cookie: visid_in|
|000001e0| 63 61 70 5f 32 34 31 30 36 32 30 3d 2f 69 63 69 |cap_2410620=/ici|
|000001f0| 51 69 55 59 54 48 43 55 32 34 75 5a 4b 30 5a 6e |QiUYTHCU24uZK0Zn|
|00000200| 67 6f 41 74 33 32 41 41 41 41 41 41 51 55 49 50 |goAt32AAAAAAQUIP|
|00000210| 41 41 41 41 41 41 44 77 49 54 67 4e 4e 71 33 49 |AAAAAADwITgNNq3I|
|00000220| 79 75 45 4e 49 37 32 63 2b 6c 65 4d 3b 20 65 78 |yuENI72c+leM; ex|
|00000230| 70 69 72 65 73 3d 53 61 74 2c 20 30 32 20 4a 75 |pires=Sat, 02 Ju|
|00000240| 6c 20 32 30 32 32 20 30 37 3a 35 30 3a 34 36 20 |l 2022 07:50:46 |
|00000250| 47 4d 54 3b 20 48 74 74 70 4f 6e 6c 79 3b 20 70 |GMT; HttpOnly; p|
|00000260| 61 74 68 3d 2f 3b 20 44 6f 6d 61 69 6e 3d 2e 64 |ath=/; Domain=.d|
|00000270| 65 63 61 74 68 6c 6f 6e 2e 6e 65 74 0d 0a 53 65 |test.net..Se.   |
|00000280| 74 2d 43 6f 6f 6b 69 65 3a 20 69 6e 63 61 70 5f |t-Cookie: incap_|
|00000290| 73 65 73 5f 31 33 36 34 5f 32 34 31 30 36 32 30 |ses_1364_2410620|
|000002a0| 3d 57 57 70 4b 61 4d 4e 67 74 67 76 72 70 4d 33 |=WWpKaMNgtgvrpM3|
|000002b0| 61 2f 65 62 74 45 6f 41 74 33 32 41 41 41 41 41 |a/ebtEoAt32AAAAA|
|000002c0| 41 52 4d 4b 62 6a 6d 43 62 39 77 68 4e 5a 4b 49 |ARMKbjmCb9whNZKI|
|000002d0| 39 34 35 37 6a 7a 51 3d 3d 3b 20 70 61 74 68 3d |9457jzQ==; path=|
|000002e0| 2f 3b 20 44 6f 6d 61 69 6e 3d 2e 64 65 63 61 74 |/; Domain=.     |
|000002f0| 68 6c 6f 6e 2e 6e 65 74 0d 0a 58 2d 43 44 4e 3a |test.net..X-CDN:|
|00000300| 20 49 6d 70 65 72 76 61 0d 0a 43 6f 6e 74 65 6e | Imperva..Conten|
|00000310| 74 2d 45 6e 63 6f 64 69 6e 67 3a 20 67 7a 69 70 |t-Encoding: gzip|
|00000320| 0d 0a 54 72 61 6e 73 66 65 72 2d 45 6e 63 6f 64 |..Transfer-Encod|
|00000330| 69 6e 67 3a 20 63 68 75 6e 6b 65 64 0d 0a 58 2d |ing: chunked..X-|
|00000340| 49 69 6e 66 6f 3a 20 31 32 2d 36 37 33 36 30 35 |Iinfo: 12-673605|
|00000350| 39 32 2d 36 37 31 30 36 33 38 30 20 70 4e 59 4e |92-67106380 pNYN|
|00000360| 20 52 54 28 31 36 32 35 32 33 38 39 30 36 39 36 | RT(162523890696|
|00000370| 35 20 35 37 30 31 29 20 71 28 30 20 30 20 30 20 |5 5701) q(0 0 0 |
|00000380| 2d 31 29 20 72 28 31 20 31 29 20 55 35 0d 0a 0d |-1) r(1 1) U5...|
|00000390| 0a                                              |.               |
+--------+-------------------------------------------------+----------------+
[piloting] [reactor-http-nio-4] [DEBUG] 2021-07-02 17:15:12.350 io.netty.util.internal.logging.Log4J2Logger: [id:e80c6acf-2, L::64171 - R:proxy-internet.org:3128] READ: 5B
         +-------------------------------------------------+
         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 30 0d 0a 0d 0a                                  |0....           |
+--------+-------------------------------------------------+----------------+
[piloting] [reactor-http-nio-4] [DEBUG] 2021-07-02 17:15:12.351 io.netty.util.internal.logging.Log4J2Logger: [id:e80c6acf-2, L::64171 - R:proxy-internet.org:3128] READ COMPLETE
[piloting] [http-nio-8090-exec-7] [DEBUG] 2021-07-02 17:16:03.307 org.springframework.web.reactive.function.client.ExchangeFunctions$DefaultExchangeFunction: [260ad3b0] Cancel signal (to close connection)
[piloting] [reactor-http-nio-4] [DEBUG] 2021-07-02 17:16:03.307 io.netty.util.internal.logging.Log4J2Logger: [id:e80c6acf-2, L:64171 - R:proxy-internet.org:3128] CLOSE

Logout without error:

 [piloting] [reactor-http-nio-4] [DEBUG] 2021-07-02 17:15:06.996 io.netty.util.internal.logging.Log4J2Logger: [id:e80c6acf-1, L:/:64171 - R:proxy-internet.org:3128] READ: 1131B
          +-------------------------------------------------+
          |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
 +--------+-------------------------------------------------+----------------+
 |00000000| 48 54 54 50 2f 31 2e 31 20 32 30 34 20 0d 0a 44 |HTTP/1.1 204 ..D|
 |00000010| 61 74 65 3a 20 46 72 69 2c 20 30 32 20 4a 75 6c |ate: Fri, 02 Jul|
 |00000020| 20 32 30 32 31 20 31 35 3a 31 35 3a 30 37 20 47 | 2021 15:15:07 G|
 |00000030| 4d 54 0d 0a 53 65 72 76 65 72 3a 20 41 70 61 63 |MT..Server: Apac|
 |00000040| 68 65 0d 0a 58 2d 43 6f 72 72 65 6c 61 74 69 6f |he..X-Correlatio|
 |00000050| 6e 2d 49 64 3a 20 32 35 37 64 30 64 30 32 2d 61 |n-Id: 257d0d02-a|
 |00000060| 37 66 34 2d 34 33 30 36 2d 62 64 30 64 2d 30 32 |7f4-4306-bd0d-02|
 |00000070| 61 37 66 34 61 33 30 36 35 66 0d 0a 58 2d 52 65 |a7f4a3065f..X-Re|
 |00000080| 71 75 65 73 74 2d 49 64 3a 20 32 35 37 64 30 64 |quest-Id: 257d0d|
 |00000090| 30 32 2d 61 37 66 34 2d 34 33 30 36 2d 62 64 30 |02-a7f4-4306-bd0|
 |000000a0| 64 2d 30 32 61 37 66 34 61 33 30 36 35 66 0d 0a |d-02a7f4a3065f..|
 |000000b0| 43 61 63 68 65 2d 43 6f 6e 74 72 6f 6c 3a 20 6e |Cache-Control: n|
 |000000c0| 6f 2d 63 61 63 68 65 2c 20 6e 6f 2d 73 74 6f 72 |o-cache, no-stor|
 |000000d0| 65 2c 20 6d 61 78 2d 61 67 65 3d 30 2c 20 6d 75 |e, max-age=0, mu|
 |000000e0| 73 74 2d 72 65 76 61 6c 69 64 61 74 65 0d 0a 43 |st-revalidate..C|
 |000000f0| 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 61 70 70 |ontent-Type: app|
 |00000100| 6c 69 63 61 74 69 6f 6e 2f 6a 73 6f 6e 3b 63 68 |lication/json;ch|
 |00000110| 61 72 73 65 74 3d 55 54 46 2d 38 0d 0a 45 78 70 |arset=UTF-8..Exp|
 |00000120| 69 72 65 73 3a 20 30 0d 0a 50 72 61 67 6d 61 3a |ires: 0..Pragma:|
 |00000130| 20 6e 6f 2d 63 61 63 68 65 0d 0a 53 65 72 76 65 | no-cache..Serve|
 |00000140| 72 2d 54 69 6d 69 6e 67 3a 20 64 74 52 70 69 64 |r-Timing: dtRpid|
 |00000150| 3b 64 65 73 63 3d 22 2d 35 30 33 37 39 39 30 32 |;desc="-50379902|
 |00000160| 33 22 0d 0a 58 2d 43 6f 6e 74 65 6e 74 2d 54 79 |3"..X-Content-Ty|
 |00000170| 70 65 2d 4f 70 74 69 6f 6e 73 3a 20 6e 6f 73 6e |pe-Options: nosn|
 |00000180| 69 66 66 0d 0a 58 2d 46 72 61 6d 65 2d 4f 70 74 |iff..X-Frame-Opt|
 |00000190| 69 6f 6e 73 3a 20 44 45 4e 59 0d 0a 58 2d 4f 6e |ions: DENY..X-On|
 |000001a0| 65 41 67 65 6e 74 2d 4a 53 2d 49 6e 6a 65 63 74 |eAgent-JS-Inject|
 |000001b0| 69 6f 6e 3a 20 74 72 75 65 0d 0a 58 2d 58 53 53 |ion: true..X-XSS|
 |000001c0| 2d 50 72 6f 74 65 63 74 69 6f 6e 3a 20 31 3b 20 |-Protection: 1; |
 |000001d0| 6d 6f 64 65 3d 62 6c 6f 63 6b 0d 0a 53 65 74 2d |mode=block..Set-|
 |000001e0| 43 6f 6f 6b 69 65 3a 20 64 74 43 6f 6f 6b 69 65 |Cookie: dtCookie|
 |000001f0| 3d 76 5f 34 5f 73 72 76 5f 34 5f 73 6e 5f 37 43 |=v_4_srv_4_sn_7C|
 |00000200| 44 32 30 41 42 43 38 44 38 42 38 45 30 36 37 35 |D20ABC8D8B8E0675|
 |00000210| 41 30 35 42 43 41 37 38 37 38 35 38 43 38 5f 70 |A05BCA787858C8_p|
 |00000220| 65 72 63 5f 31 30 30 30 30 30 5f 6f 6c 5f 30 5f |erc_100000_ol_0_|
 |00000230| 6d 75 6c 5f 31 5f 61 70 70 2d 33 41 65 61 37 63 |mul_1_app-3Aea7c|
 |00000240| 34 62 35 39 66 32 37 64 34 33 65 62 5f 31 3b 20 |4b59f27d43eb_1; |
 |00000250| 50 61 74 68 3d 2f 3b 20 44 6f 6d 61 69 6e 3d 2e |Path=/; Domain=.|
 |00000260| 64 65 63 61 74 68 6c 6f 6e 2e 6e 65 74 0d 0a 56 |test.net..V     |
 |00000270| 69 61 3a 20 31 2e 31 20 61 70 69 2e 64 65 63 61 |ia: 1.1 api.test|
 |00000280| 74 68 6c 6f 6e 2e 6e 65 74 2c 20 31 2e 31 20 67 |      .net,1.1 g|
 |00000290| 6f 6f 67 6c 65 0d 0a 41 6c 74 2d 53 76 63 3a 20 |oogle..Alt-Svc: |
 |000002a0| 63 6c 65 61 72 0d 0a 53 65 74 2d 43 6f 6f 6b 69 |clear..Set-Cooki|
 |000002b0| 65 3a 20 76 69 73 69 64 5f 69 6e 63 61 70 5f 32 |e: visid_incap_2|
 |000002c0| 34 31 30 36 32 30 3d 5a 64 7a 5a 47 64 48 77 53 |410620=ZdzZGdHwS|
 |000002d0| 53 4b 4a 48 59 48 50 51 6f 70 42 57 58 73 74 33 |SKJHYHPQopBWXst3|
 |000002e0| 32 41 41 41 41 41 41 51 55 49 50 41 41 41 41 41 |2AAAAAAQUIPAAAAA|
 |000002f0| 41 43 5a 72 38 4d 75 70 6f 41 59 6c 38 4a 63 61 |ACZr8MupoAYl8Jca|
 |00000300| 54 67 46 54 49 76 53 3b 20 65 78 70 69 72 65 73 |TgFTIvS; expires|
 |00000310| 3d 53 61 74 2c 20 30 32 20 4a 75 6c 20 32 30 32 |=Sat, 02 Jul 202|
 |00000320| 32 20 30 37 3a 35 30 3a 34 36 20 47 4d 54 3b 20 |2 07:50:46 GMT; |
 |00000330| 48 74 74 70 4f 6e 6c 79 3b 20 70 61 74 68 3d 2f |HttpOnly; path=/|
 |00000340| 3b 20 44 6f 6d 61 69 6e 3d 2e 64 65 63 61 74 68 |; Domain=.test  |
 |00000350| 6c 6f 6e 2e 6e 65 74 0d 0a 53 65 74 2d 43 6f 6f |   .net..Set-Coo|
 |00000360| 6b 69 65 3a 20 69 6e 63 61 70 5f 73 65 73 5f 31 |kie: incap_ses_1|
 |00000370| 33 36 34 5f 32 34 31 30 36 32 30 3d 7a 63 6e 6b |364_2410620=zcnk|
 |00000380| 57 35 6f 65 58 46 49 67 6d 73 33 61 2f 65 62 74 |W5oeXFIgms3a/ebt|
 |00000390| 45 6e 73 74 33 32 41 41 41 41 41 41 34 2b 73 6c |Enst32AAAAAA4+sl|
 |000003a0| 75 33 37 41 69 64 4e 39 74 63 4a 45 39 6a 30 55 |u37AidN9tcJE9j0U|
 |000003b0| 63 51 3d 3d 3b 20 70 61 74 68 3d 2f 3b 20 44 6f |cQ==; path=/; Do|
 |000003c0| 6d 61 69 6e 3d 2e 64 65 63 61 74 68 6c 6f 6e 2e |main=.test.     |
 |000003d0| 6e 65 74 0d 0a 58 2d 43 44 4e 3a 20 49 6d 70 65 |net..X-CDN: Impe|
 |000003e0| 72 76 61 0d 0a 43 6f 6e 74 65 6e 74 2d 45 6e 63 |rva..Content-Enc|
 |000003f0| 6f 64 69 6e 67 3a 20 67 7a 69 70 0d 0a 54 72 61 |oding: gzip..Tra|
 |00000400| 6e 73 66 65 72 2d 45 6e 63 6f 64 69 6e 67 3a 20 |nsfer-Encoding: |
 |00000410| 63 68 75 6e 6b 65 64 0d 0a 58 2d 49 69 6e 66 6f |chunked..X-Iinfo|
 |00000420| 3a 20 31 32 2d 36 37 33 36 30 35 39 32 2d 36 37 |: 12-67360592-67|
 |00000430| 31 30 36 33 38 30 20 70 4e 59 4e 20 52 54 28 31 |106380 pNYN RT(1|
 |00000440| 36 32 35 32 33 38 39 30 36 39 36 35 20 32 39 35 |625238906965 295|
 |00000450| 29 20 71 28 30 20 30 20 30 20 2d 31 29 20 72 28 |) q(0 0 0 -1) r(|
 |00000460| 31 20 31 29 20 55 35 0d 0a 0d 0a                |1 1) U5....     |
 +--------+-------------------------------------------------+----------------+
 [piloting] [reactor-http-nio-4] [DEBUG] 2021-07-02 17:15:06.997 org.springframework.core.log.LogFormatUtils: [6215dde9] [e80c6acf-1] Response 204 NO_CONTENT
  • What is the expected behaviour? Because `Mono.just(emptyList());` this line will never get run. This is only a declaration. You should return something like `return Mono.empy();` – Toerktumlare Jul 06 '21 at 17:47
  • i think my request is not clear, i try this to add a breakpoint just to see if my application going to this point but sometime he is block at "exchangeToMono" and waiting 50sec (timeout) to end my request. – Matthieu POUDROUX Jul 07 '21 at 05:58

1 Answers1

0
if(status.equals(NO_CONTENT)){
   Mono.just(emptyList());
}
return clientResponse.bodyToMono(DateKpi.class);

With the code snippet above, when the status code is 204 (NO CONTENT) then bodyToMono will always be invoked. bodyToMono will emit an empty Mono (Mono.empty) in this case.

If the desired outcome is to return a Mono with an empty list as the value then code should be something along the lines of

if(status.equals(NO_CONTENT)){
   return Mono.just(emptyList());
}
return clientResponse.bodyToMono(DateKpi.class);
Michael McFadyen
  • 2,675
  • 11
  • 25
  • i think my request is not clear, i try this to add a breakpoint just to see if my application going to this point but sometime he is block at "exchangeToMono" and waiting 50sec (timeout) to end my request. – Matthieu POUDROUX Jul 07 '21 at 05:57
  • ok, so there might be more than one issue going on in your code then. Regardless of if the code is hanging on `exchangeToMono`, the code snippet above is wrong and will also need to be fixed for your app to handle `NO_CONTENT` responses correctly – Michael McFadyen Jul 09 '21 at 08:54