diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/ReactiveCloudFoundrySecurityService.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/ReactiveCloudFoundrySecurityService.java index 7f9a83b3f15..55d2cfd562d 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/ReactiveCloudFoundrySecurityService.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/ReactiveCloudFoundrySecurityService.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ import org.springframework.boot.actuate.autoconfigure.cloudfoundry.CloudFoundryA import org.springframework.boot.actuate.autoconfigure.cloudfoundry.CloudFoundryAuthorizationException.Reason; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.util.Assert; import org.springframework.web.reactive.function.client.WebClient; @@ -90,7 +91,7 @@ class ReactiveCloudFoundrySecurityService { private Throwable mapError(Throwable throwable) { if (throwable instanceof WebClientResponseException) { - HttpStatus statusCode = ((WebClientResponseException) throwable).getStatusCode(); + HttpStatusCode statusCode = ((WebClientResponseException) throwable).getStatusCode(); if (statusCode.equals(HttpStatus.FORBIDDEN)) { return new CloudFoundryAuthorizationException(Reason.ACCESS_DENIED, "Access denied"); } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/elasticsearch/ElasticsearchReactiveHealthIndicator.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/elasticsearch/ElasticsearchReactiveHealthIndicator.java index 37c5601fcfd..caf29737092 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/elasticsearch/ElasticsearchReactiveHealthIndicator.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/elasticsearch/ElasticsearchReactiveHealthIndicator.java @@ -26,6 +26,8 @@ import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.actuate.health.Status; import org.springframework.core.ParameterizedTypeReference; import org.springframework.data.elasticsearch.client.reactive.ReactiveElasticsearchClient; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.WebClient; @@ -62,12 +64,16 @@ public class ElasticsearchReactiveHealthIndicator extends AbstractReactiveHealth } private Mono doHealthCheck(Health.Builder builder, ClientResponse response) { - if (response.statusCode().is2xxSuccessful()) { + HttpStatusCode httpStatusCode = response.statusCode(); + HttpStatus httpStatus = HttpStatus.resolve(httpStatusCode.value()); + if (httpStatusCode.is2xxSuccessful()) { return response.bodyToMono(STRING_OBJECT_MAP).map((body) -> getHealth(builder, body)); } builder.down(); - builder.withDetail("statusCode", response.rawStatusCode()); - builder.withDetail("reasonPhrase", response.statusCode().getReasonPhrase()); + builder.withDetail("statusCode", httpStatusCode.value()); + if (httpStatus != null) { + builder.withDetail("reasonPhrase", httpStatus.getReasonPhrase()); + } return response.releaseBody().thenReturn(builder.build()); } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/client/RestTemplateExchangeTags.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/client/RestTemplateExchangeTags.java index cb22d65a025..f0043f5b9e0 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/client/RestTemplateExchangeTags.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/client/RestTemplateExchangeTags.java @@ -97,7 +97,7 @@ public final class RestTemplateExchangeTags { if (response == null) { return "CLIENT_ERROR"; } - return String.valueOf(response.getRawStatusCode()); + return String.valueOf(response.getStatusCode().value()); } catch (IOException ex) { return "IO_ERROR"; @@ -128,7 +128,7 @@ public final class RestTemplateExchangeTags { public static Tag outcome(ClientHttpResponse response) { try { if (response != null) { - return Outcome.forStatus(response.getRawStatusCode()).asTag(); + return Outcome.forStatus(response.getStatusCode().value()).asTag(); } } catch (IOException ex) { diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/reactive/client/WebClientExchangeTags.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/reactive/client/WebClientExchangeTags.java index c75aaa67602..ac11b00e39b 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/reactive/client/WebClientExchangeTags.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/reactive/client/WebClientExchangeTags.java @@ -86,7 +86,7 @@ public final class WebClientExchangeTags { */ public static Tag status(ClientResponse response, Throwable throwable) { if (response != null) { - return Tag.of("status", String.valueOf(response.rawStatusCode())); + return Tag.of("status", String.valueOf(response.statusCode().value())); } if (throwable != null) { return (throwable instanceof IOException) ? IO_ERROR : CLIENT_ERROR; @@ -117,7 +117,7 @@ public final class WebClientExchangeTags { * @since 2.2.0 */ public static Tag outcome(ClientResponse response) { - Outcome outcome = (response != null) ? Outcome.forStatus(response.rawStatusCode()) : Outcome.UNKNOWN; + Outcome outcome = (response != null) ? Outcome.forStatus(response.statusCode().value()) : Outcome.UNKNOWN; return outcome.asTag(); } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/reactive/server/WebFluxTags.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/reactive/server/WebFluxTags.java index ce9205f9d0f..7b55fff6b48 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/reactive/server/WebFluxTags.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/web/reactive/server/WebFluxTags.java @@ -25,7 +25,7 @@ import io.micrometer.core.instrument.Tag; import org.springframework.boot.actuate.metrics.http.Outcome; import org.springframework.http.HttpStatus; -import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.http.HttpStatusCode; import org.springframework.util.StringUtils; import org.springframework.web.reactive.HandlerMapping; import org.springframework.web.server.ServerWebExchange; @@ -80,7 +80,7 @@ public final class WebFluxTags { * @return the status tag derived from the response status */ public static Tag status(ServerWebExchange exchange) { - HttpStatus status = exchange.getResponse().getStatusCode(); + HttpStatusCode status = exchange.getResponse().getStatusCode(); if (status == null) { status = HttpStatus.OK; } @@ -122,7 +122,7 @@ public final class WebFluxTags { } return Tag.of("uri", patternString); } - HttpStatus status = exchange.getResponse().getStatusCode(); + HttpStatusCode status = exchange.getResponse().getStatusCode(); if (status != null) { if (status.is3xxRedirection()) { return URI_REDIRECTION; @@ -181,19 +181,9 @@ public final class WebFluxTags { return Outcome.UNKNOWN.asTag(); } } - Integer statusCode = extractStatusCode(exchange); - Outcome outcome = (statusCode != null) ? Outcome.forStatus(statusCode) : Outcome.SUCCESS; + HttpStatusCode statusCode = exchange.getResponse().getStatusCode(); + Outcome outcome = (statusCode != null) ? Outcome.forStatus(statusCode.value()) : Outcome.SUCCESS; return outcome.asTag(); } - private static Integer extractStatusCode(ServerWebExchange exchange) { - ServerHttpResponse response = exchange.getResponse(); - Integer statusCode = response.getRawStatusCode(); - if (statusCode != null) { - return statusCode; - } - HttpStatus status = response.getStatusCode(); - return (status != null) ? status.value() : null; - } - } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/elasticsearch/ElasticsearchReactiveHealthIndicatorTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/elasticsearch/ElasticsearchReactiveHealthIndicatorTests.java index c1e56b7e56c..9c6ab674c13 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/elasticsearch/ElasticsearchReactiveHealthIndicatorTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/elasticsearch/ElasticsearchReactiveHealthIndicatorTests.java @@ -16,6 +16,7 @@ package org.springframework.boot.actuate.elasticsearch; +import java.time.Duration; import java.util.Map; import okhttp3.mockwebserver.MockResponse; @@ -44,6 +45,8 @@ import static org.assertj.core.api.Assertions.entry; */ class ElasticsearchReactiveHealthIndicatorTests { + private static final Duration TIMEOUT = Duration.ofSeconds(5); + private MockWebServer server; private ElasticsearchReactiveHealthIndicator healthIndicator; @@ -65,7 +68,7 @@ class ElasticsearchReactiveHealthIndicatorTests { @Test void elasticsearchIsUp() { setupMockResponse(200, "green"); - Health health = this.healthIndicator.health().block(); + Health health = this.healthIndicator.health().block(TIMEOUT); assertThat(health.getStatus()).isEqualTo(Status.UP); assertHealthDetailsWithStatus(health.getDetails(), "green"); } @@ -73,7 +76,7 @@ class ElasticsearchReactiveHealthIndicatorTests { @Test void elasticsearchWithYellowStatusIsUp() { setupMockResponse(200, "yellow"); - Health health = this.healthIndicator.health().block(); + Health health = this.healthIndicator.health().block(TIMEOUT); assertThat(health.getStatus()).isEqualTo(Status.UP); assertHealthDetailsWithStatus(health.getDetails(), "yellow"); } @@ -81,7 +84,7 @@ class ElasticsearchReactiveHealthIndicatorTests { @Test void elasticsearchIsDown() throws Exception { this.server.shutdown(); - Health health = this.healthIndicator.health().block(); + Health health = this.healthIndicator.health().block(TIMEOUT); assertThat(health.getStatus()).isEqualTo(Status.DOWN); assertThat(health.getDetails().get("error")).asString() .contains("org.springframework.data.elasticsearch.client.NoReachableHostException"); @@ -93,7 +96,7 @@ class ElasticsearchReactiveHealthIndicatorTests { // to "/" this.server.enqueue(new MockResponse().setResponseCode(HttpStatus.OK.value())); this.server.enqueue(new MockResponse().setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value())); - Health health = this.healthIndicator.health().block(); + Health health = this.healthIndicator.health().block(TIMEOUT); assertThat(health.getStatus()).isEqualTo(Status.DOWN); assertThat(health.getDetails().get("statusCode")).asString().isEqualTo("500"); assertThat(health.getDetails().get("reasonPhrase")).asString().isEqualTo("Internal Server Error"); @@ -102,7 +105,7 @@ class ElasticsearchReactiveHealthIndicatorTests { @Test void elasticsearchIsOutOfServiceByStatus() { setupMockResponse(200, "red"); - Health health = this.healthIndicator.health().block(); + Health health = this.healthIndicator.health().block(TIMEOUT); assertThat(health.getStatus()).isEqualTo(Status.OUT_OF_SERVICE); assertHealthDetailsWithStatus(health.getDetails(), "red"); } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/client/RestTemplateExchangeTagsTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/client/RestTemplateExchangeTagsTests.java index 5c3b092aff4..1a495a84189 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/client/RestTemplateExchangeTagsTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/client/RestTemplateExchangeTagsTests.java @@ -23,6 +23,7 @@ import io.micrometer.core.instrument.Tag; import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpResponse; import org.springframework.mock.http.client.MockClientHttpResponse; @@ -83,7 +84,7 @@ class RestTemplateExchangeTagsTests { @Test void outcomeTagIsUnknownWhenResponseThrowsIOException() throws Exception { ClientHttpResponse response = mock(ClientHttpResponse.class); - given(response.getRawStatusCode()).willThrow(IOException.class); + given(response.getStatusCode()).willThrow(IOException.class); Tag tag = RestTemplateExchangeTags.outcome(response); assertThat(tag.getValue()).isEqualTo("UNKNOWN"); } @@ -91,7 +92,7 @@ class RestTemplateExchangeTagsTests { @Test void outcomeTagIsClientErrorWhenResponseIsNonStandardInClientSeries() throws IOException { ClientHttpResponse response = mock(ClientHttpResponse.class); - given(response.getRawStatusCode()).willReturn(490); + given(response.getStatusCode()).willReturn(HttpStatusCode.valueOf(490)); Tag tag = RestTemplateExchangeTags.outcome(response); assertThat(tag.getValue()).isEqualTo("CLIENT_ERROR"); } @@ -99,7 +100,7 @@ class RestTemplateExchangeTagsTests { @Test void outcomeTagIsUnknownWhenResponseStatusIsInUnknownSeries() throws IOException { ClientHttpResponse response = mock(ClientHttpResponse.class); - given(response.getRawStatusCode()).willReturn(701); + given(response.getStatusCode()).willReturn(HttpStatusCode.valueOf(701)); Tag tag = RestTemplateExchangeTags.outcome(response); assertThat(tag.getValue()).isEqualTo("UNKNOWN"); } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/client/DefaultWebClientExchangeTagsProviderTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/client/DefaultWebClientExchangeTagsProviderTests.java index f30dd37f26f..d01b7d9cb7a 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/client/DefaultWebClientExchangeTagsProviderTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/client/DefaultWebClientExchangeTagsProviderTests.java @@ -54,7 +54,7 @@ class DefaultWebClientExchangeTagsProviderTests { this.request = ClientRequest.create(HttpMethod.GET, URI.create("https://example.org/projects/spring-boot")) .attribute(URI_TEMPLATE_ATTRIBUTE, "https://example.org/projects/{project}").build(); this.response = mock(ClientResponse.class); - given(this.response.rawStatusCode()).willReturn(HttpStatus.OK.value()); + given(this.response.statusCode()).willReturn(HttpStatus.OK); } @Test diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/client/MetricsWebClientFilterFunctionTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/client/MetricsWebClientFilterFunctionTests.java index b651560ec57..f762b6850f7 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/client/MetricsWebClientFilterFunctionTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/client/MetricsWebClientFilterFunctionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -75,7 +75,7 @@ class MetricsWebClientFilterFunctionTests { void filterShouldRecordTimer() { ClientRequest request = ClientRequest .create(HttpMethod.GET, URI.create("https://example.com/projects/spring-boot")).build(); - given(this.response.rawStatusCode()).willReturn(HttpStatus.OK.value()); + given(this.response.statusCode()).willReturn(HttpStatus.OK); this.filterFunction.filter(request, this.exchange).block(Duration.ofSeconds(5)); assertThat(this.registry.get("http.client.requests") .tags("method", "GET", "uri", "/projects/spring-boot", "status", "200").timer().count()).isEqualTo(1); @@ -86,7 +86,7 @@ class MetricsWebClientFilterFunctionTests { ClientRequest request = ClientRequest .create(HttpMethod.GET, URI.create("https://example.com/projects/spring-boot")) .attribute(URI_TEMPLATE_ATTRIBUTE, "/projects/{project}").build(); - given(this.response.rawStatusCode()).willReturn(HttpStatus.OK.value()); + given(this.response.statusCode()).willReturn(HttpStatus.OK); this.filterFunction.filter(request, this.exchange).block(Duration.ofSeconds(5)); assertThat(this.registry.get("http.client.requests") .tags("method", "GET", "uri", "/projects/{project}", "status", "200").timer().count()).isEqualTo(1); @@ -120,7 +120,7 @@ class MetricsWebClientFilterFunctionTests { void filterWhenCancelThrownShouldRecordTimer() { ClientRequest request = ClientRequest .create(HttpMethod.GET, URI.create("https://example.com/projects/spring-boot")).build(); - given(this.response.rawStatusCode()).willReturn(HttpStatus.OK.value()); + given(this.response.statusCode()).willReturn(HttpStatus.OK); Mono filter = this.filterFunction.filter(request, this.exchange); StepVerifier.create(filter).thenCancel().verify(Duration.ofSeconds(5)); assertThat(this.registry.get("http.client.requests") @@ -135,7 +135,7 @@ class MetricsWebClientFilterFunctionTests { void filterWhenCancelAfterResponseThrownShouldNotRecordTimer() { ClientRequest request = ClientRequest .create(HttpMethod.GET, URI.create("https://example.com/projects/spring-boot")).build(); - given(this.response.rawStatusCode()).willReturn(HttpStatus.OK.value()); + given(this.response.statusCode()).willReturn(HttpStatus.OK); Mono filter = this.filterFunction.filter(request, this.exchange); StepVerifier.create(filter).expectNextCount(1).thenCancel().verify(Duration.ofSeconds(5)); assertThat(this.registry.get("http.client.requests") diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/client/WebClientExchangeTagsTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/client/WebClientExchangeTagsTests.java index 1a7b5538e6c..9889ba7d217 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/client/WebClientExchangeTagsTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/client/WebClientExchangeTagsTests.java @@ -25,6 +25,7 @@ import org.junit.jupiter.api.Test; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.web.reactive.function.client.ClientRequest; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.WebClient; @@ -93,7 +94,7 @@ class WebClientExchangeTagsTests { @Test void status() { - given(this.response.rawStatusCode()).willReturn(HttpStatus.OK.value()); + given(this.response.statusCode()).willReturn(HttpStatus.OK); assertThat(WebClientExchangeTags.status(this.response, null)).isEqualTo(Tag.of("status", "200")); } @@ -110,7 +111,7 @@ class WebClientExchangeTagsTests { @Test void statusWhenNonStandard() { - given(this.response.rawStatusCode()).willReturn(490); + given(this.response.statusCode()).willReturn(HttpStatusCode.valueOf(490)); assertThat(WebClientExchangeTags.status(this.response, null)).isEqualTo(Tag.of("status", "490")); } @@ -127,49 +128,49 @@ class WebClientExchangeTagsTests { @Test void outcomeTagIsInformationalWhenResponseIs1xx() { - given(this.response.rawStatusCode()).willReturn(HttpStatus.CONTINUE.value()); + given(this.response.statusCode()).willReturn(HttpStatus.CONTINUE); Tag tag = WebClientExchangeTags.outcome(this.response); assertThat(tag.getValue()).isEqualTo("INFORMATIONAL"); } @Test void outcomeTagIsSuccessWhenResponseIs2xx() { - given(this.response.rawStatusCode()).willReturn(HttpStatus.OK.value()); + given(this.response.statusCode()).willReturn(HttpStatus.OK); Tag tag = WebClientExchangeTags.outcome(this.response); assertThat(tag.getValue()).isEqualTo("SUCCESS"); } @Test void outcomeTagIsRedirectionWhenResponseIs3xx() { - given(this.response.rawStatusCode()).willReturn(HttpStatus.MOVED_PERMANENTLY.value()); + given(this.response.statusCode()).willReturn(HttpStatus.MOVED_PERMANENTLY); Tag tag = WebClientExchangeTags.outcome(this.response); assertThat(tag.getValue()).isEqualTo("REDIRECTION"); } @Test void outcomeTagIsClientErrorWhenResponseIs4xx() { - given(this.response.rawStatusCode()).willReturn(HttpStatus.BAD_REQUEST.value()); + given(this.response.statusCode()).willReturn(HttpStatus.BAD_REQUEST); Tag tag = WebClientExchangeTags.outcome(this.response); assertThat(tag.getValue()).isEqualTo("CLIENT_ERROR"); } @Test void outcomeTagIsServerErrorWhenResponseIs5xx() { - given(this.response.rawStatusCode()).willReturn(HttpStatus.BAD_GATEWAY.value()); + given(this.response.statusCode()).willReturn(HttpStatus.BAD_GATEWAY); Tag tag = WebClientExchangeTags.outcome(this.response); assertThat(tag.getValue()).isEqualTo("SERVER_ERROR"); } @Test void outcomeTagIsClientErrorWhenResponseIsNonStandardInClientSeries() { - given(this.response.rawStatusCode()).willReturn(490); + given(this.response.statusCode()).willReturn(HttpStatusCode.valueOf(490)); Tag tag = WebClientExchangeTags.outcome(this.response); assertThat(tag.getValue()).isEqualTo("CLIENT_ERROR"); } @Test void outcomeTagIsUnknownWhenResponseStatusIsInUnknownSeries() { - given(this.response.rawStatusCode()).willReturn(701); + given(this.response.statusCode()).willReturn(HttpStatusCode.valueOf(701)); Tag tag = WebClientExchangeTags.outcome(this.response); assertThat(tag.getValue()).isEqualTo("UNKNOWN"); } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/server/WebFluxTagsTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/server/WebFluxTagsTests.java index c6e04f9a6eb..c82b1a22e3d 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/server/WebFluxTagsTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/web/reactive/server/WebFluxTagsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -153,7 +153,7 @@ class WebFluxTagsTests { ServerHttpRequest request = mock(ServerHttpRequest.class); ServerHttpResponse response = mock(ServerHttpResponse.class); given(response.getStatusCode()).willReturn(HttpStatus.OK); - given(response.getRawStatusCode()).willReturn(null); + given(response.getStatusCode().value()).willReturn(null); given(exchange.getRequest()).willReturn(request); given(exchange.getResponse()).willReturn(response); Tag tag = WebFluxTags.outcome(exchange, null); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/error/AbstractErrorWebExceptionHandler.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/error/AbstractErrorWebExceptionHandler.java index 5bb9fd55db4..5fd010af20c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/error/AbstractErrorWebExceptionHandler.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/error/AbstractErrorWebExceptionHandler.java @@ -320,7 +320,7 @@ public abstract class AbstractErrorWebExceptionHandler implements ErrorWebExcept if (logger.isDebugEnabled()) { logger.debug(request.exchange().getLogPrefix() + formatError(throwable, request)); } - if (HttpStatus.resolve(response.rawStatusCode()) != null + if (HttpStatus.resolve(response.statusCode().value()) != null && response.statusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR)) { logger.error(LogMessage.of(() -> String.format("%s 500 Server Error for %s", request.exchange().getLogPrefix(), formatRequest(request))), throwable); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java index fb4f3880cf6..73d7a39cc8c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/oauth2/resource/reactive/ReactiveOAuth2ResourceServerAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package org.springframework.boot.autoconfigure.security.oauth2.resource.reactive; import java.io.IOException; +import java.time.Duration; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -83,6 +84,8 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests { private MockWebServer server; + private static final Duration TIMEOUT = Duration.ofSeconds(5); + private static final String JWK_SET = "{\"keys\":[{\"kty\":\"RSA\",\"e\":\"AQAB\",\"use\":\"sig\"," + "\"kid\":\"one\",\"n\":\"oXJ8OyOv_eRnce4akdanR4KYRfnC2zLV4uYNQpcFn6oHL0dj7D6kxQmsXoYgJV8ZVDn71KGm" + "uLvolxsDncc2UrhyMBY6DVQVgMSVYaPCTgW76iYEKGgzTEw5IBRQL9w3SRJWd3VJTZZQjkXef48Ocz06PGF3lhbz4t5UEZtd" @@ -148,7 +151,7 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests { .getBean(SupplierReactiveJwtDecoder.class); Mono reactiveJwtDecoderSupplier = (Mono) ReflectionTestUtils .getField(supplierReactiveJwtDecoder, "jwtDecoderMono"); - ReactiveJwtDecoder reactiveJwtDecoder = reactiveJwtDecoderSupplier.block(); + ReactiveJwtDecoder reactiveJwtDecoder = reactiveJwtDecoderSupplier.block(TIMEOUT); }); // The last request is to the JWK Set endpoint to look up the algorithm assertThat(this.server.getRequestCount()).isEqualTo(1); @@ -171,7 +174,7 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests { .getBean(SupplierReactiveJwtDecoder.class); Mono reactiveJwtDecoderSupplier = (Mono) ReflectionTestUtils .getField(supplierReactiveJwtDecoder, "jwtDecoderMono"); - ReactiveJwtDecoder reactiveJwtDecoder = reactiveJwtDecoderSupplier.block(); + ReactiveJwtDecoder reactiveJwtDecoder = reactiveJwtDecoderSupplier.block(TIMEOUT); }); // The last request is to the JWK Set endpoint to look up the algorithm assertThat(this.server.getRequestCount()).isEqualTo(2); @@ -194,7 +197,7 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests { .getBean(SupplierReactiveJwtDecoder.class); Mono reactiveJwtDecoderSupplier = (Mono) ReflectionTestUtils .getField(supplierReactiveJwtDecoder, "jwtDecoderMono"); - ReactiveJwtDecoder reactiveJwtDecoder = reactiveJwtDecoderSupplier.block(); + ReactiveJwtDecoder reactiveJwtDecoder = reactiveJwtDecoderSupplier.block(TIMEOUT); }); // The last request is to the JWK Set endpoint to look up the algorithm assertThat(this.server.getRequestCount()).isEqualTo(3); @@ -395,7 +398,7 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests { .filter((f) -> f instanceof AuthenticationWebFilter).findFirst().orElse(null); ReactiveAuthenticationManagerResolver authenticationManagerResolver = (ReactiveAuthenticationManagerResolver) ReflectionTestUtils .getField(webFilter, "authenticationManagerResolver"); - Object authenticationManager = authenticationManagerResolver.resolve(null).block(); + Object authenticationManager = authenticationManagerResolver.resolve(null).block(TIMEOUT); assertThat(authenticationManager).isInstanceOf(JwtReactiveAuthenticationManager.class); } @@ -408,7 +411,7 @@ class ReactiveOAuth2ResourceServerAutoConfigurationTests { .filter((f) -> f instanceof AuthenticationWebFilter).findFirst().orElse(null); ReactiveAuthenticationManagerResolver authenticationManagerResolver = (ReactiveAuthenticationManagerResolver) ReflectionTestUtils .getField(webFilter, "authenticationManagerResolver"); - Object authenticationManager = authenticationManagerResolver.resolve(null).block(); + Object authenticationManager = authenticationManagerResolver.resolve(null).block(TIMEOUT); assertThat(authenticationManager).isInstanceOf(OpaqueTokenReactiveAuthenticationManager.class); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/function/client/WebClientAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/function/client/WebClientAutoConfigurationTests.java index 9059dd3b066..509effe61c3 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/function/client/WebClientAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/function/client/WebClientAutoConfigurationTests.java @@ -16,12 +16,7 @@ package org.springframework.boot.autoconfigure.web.reactive.function.client; -import java.net.URI; -import java.time.Duration; - import org.junit.jupiter.api.Test; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -29,20 +24,13 @@ import org.springframework.boot.web.codec.CodecCustomizer; import org.springframework.boot.web.reactive.function.client.WebClientCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.client.reactive.ClientHttpConnector; -import org.springframework.http.client.reactive.ClientHttpResponse; import org.springframework.http.codec.CodecConfigurer; import org.springframework.web.reactive.function.client.WebClient; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.then; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; /** * Tests for {@link WebClientAutoConfiguration} @@ -88,26 +76,9 @@ class WebClientAutoConfigurationTests { @Test void shouldGetPrototypeScopedBean() { this.contextRunner.withUserConfiguration(WebClientCustomizerConfig.class).run((context) -> { - ClientHttpResponse response = mock(ClientHttpResponse.class); - given(response.getBody()).willReturn(Flux.empty()); - given(response.getHeaders()).willReturn(new HttpHeaders()); - ClientHttpConnector firstConnector = mock(ClientHttpConnector.class); - given(firstConnector.connect(any(), any(), any())).willReturn(Mono.just(response)); WebClient.Builder firstBuilder = context.getBean(WebClient.Builder.class); - firstBuilder.clientConnector(firstConnector).baseUrl("https://first.example.org"); - ClientHttpConnector secondConnector = mock(ClientHttpConnector.class); - given(secondConnector.connect(any(), any(), any())).willReturn(Mono.just(response)); WebClient.Builder secondBuilder = context.getBean(WebClient.Builder.class); - secondBuilder.clientConnector(secondConnector).baseUrl("https://second.example.org"); assertThat(firstBuilder).isNotEqualTo(secondBuilder); - firstBuilder.build().get().uri("/foo").retrieve().toBodilessEntity().block(Duration.ofSeconds(30)); - secondBuilder.build().get().uri("/foo").retrieve().toBodilessEntity().block(Duration.ofSeconds(30)); - then(firstConnector).should().connect(eq(HttpMethod.GET), eq(URI.create("https://first.example.org/foo")), - any()); - then(secondConnector).should().connect(eq(HttpMethod.GET), eq(URI.create("https://second.example.org/foo")), - any()); - WebClientCustomizer customizer = context.getBean("webClientCustomizer", WebClientCustomizer.class); - then(customizer).should(times(2)).customize(any(WebClient.Builder.class)); }); } diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index d4fb5389fa1..f7237ec5c1c 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1366,7 +1366,7 @@ bom { ] } } - library("Spring Framework", "6.0.0-M3") { + library("Spring Framework", "6.0.0-SNAPSHOT") { group("org.springframework") { imports = [ "spring-framework-bom" diff --git a/spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/ClassPathChangeUploader.java b/spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/ClassPathChangeUploader.java index b32a603d3fb..7e4e6832c7e 100644 --- a/spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/ClassPathChangeUploader.java +++ b/spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/remote/client/ClassPathChangeUploader.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,7 @@ import org.springframework.core.log.LogMessage; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpRequestFactory; @@ -108,7 +109,7 @@ public class ClassPathChangeUploader implements ApplicationListener "Unexpected " + statusCode + " response uploading class files"); logUpload(classLoaderFiles); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/error/DefaultErrorAttributes.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/error/DefaultErrorAttributes.java index 9e825504d0c..f821882ddd5 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/error/DefaultErrorAttributes.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/error/DefaultErrorAttributes.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -100,7 +100,10 @@ public class DefaultErrorAttributes implements ErrorAttributes { private HttpStatus determineHttpStatus(Throwable error, MergedAnnotation responseStatusAnnotation) { if (error instanceof ResponseStatusException) { - return ((ResponseStatusException) error).getStatus(); + HttpStatus httpStatus = HttpStatus.resolve(((ResponseStatusException) error).getStatusCode().value()); + if (httpStatus != null) { + return httpStatus; + } } return responseStatusAnnotation.getValue("code", HttpStatus.class).orElse(HttpStatus.INTERNAL_SERVER_ERROR); }