diff --git a/framework-docs/src/main/kotlin/org/springframework/docs/web/webmvc/mvccontroller/mvcannexceptionhandlerexc/ExceptionController.kt b/framework-docs/src/main/kotlin/org/springframework/docs/web/webmvc/mvccontroller/mvcannexceptionhandlerexc/ExceptionController.kt index dda49e8f08b2..3e787b0a18e6 100644 --- a/framework-docs/src/main/kotlin/org/springframework/docs/web/webmvc/mvccontroller/mvcannexceptionhandlerexc/ExceptionController.kt +++ b/framework-docs/src/main/kotlin/org/springframework/docs/web/webmvc/mvccontroller/mvcannexceptionhandlerexc/ExceptionController.kt @@ -27,7 +27,7 @@ class ExceptionController { // tag::narrow[] @ExceptionHandler(FileSystemException::class, RemoteException::class) - fun handleIoException(ex: IOException): ResponseEntity { + fun handleIoException(ex: IOException): ResponseEntity { return ResponseEntity.internalServerError().body(ex.message) } // end::narrow[] @@ -35,7 +35,7 @@ class ExceptionController { // tag::general[] @ExceptionHandler(FileSystemException::class, RemoteException::class) - fun handleExceptions(ex: Exception): ResponseEntity { + fun handleExceptions(ex: Exception): ResponseEntity { return ResponseEntity.internalServerError().body(ex.message) } // end::general[] diff --git a/spring-web/src/main/java/org/springframework/http/HttpEntity.java b/spring-web/src/main/java/org/springframework/http/HttpEntity.java index d55a6b891727..e58a984df31b 100644 --- a/spring-web/src/main/java/org/springframework/http/HttpEntity.java +++ b/spring-web/src/main/java/org/springframework/http/HttpEntity.java @@ -56,7 +56,7 @@ * @see #getBody() * @see #getHeaders() */ -public class HttpEntity { +public class HttpEntity { /** * An {@code HttpEntity} instance with a {@code null} body and @@ -67,12 +67,13 @@ public class HttpEntity { private final HttpHeaders headers; - private final @Nullable T body; + private final T body; /** * Create a new, empty {@code HttpEntity}. */ + @SuppressWarnings("NullAway") protected HttpEntity() { this(null, (HttpHeaders) null); } @@ -90,6 +91,7 @@ public HttpEntity(T body) { * @param headers the entity headers * @since 7.0 */ + @SuppressWarnings("NullAway") public HttpEntity(HttpHeaders headers) { this(null, headers); } @@ -100,7 +102,7 @@ public HttpEntity(HttpHeaders headers) { * @param headers the entity headers * @since 7.0 */ - public HttpEntity(@Nullable T body, @Nullable HttpHeaders headers) { + public HttpEntity(T body, @Nullable HttpHeaders headers) { this.body = body; this.headers = (headers != null) ? headers : new HttpHeaders(); } @@ -110,6 +112,7 @@ public HttpEntity(@Nullable T body, @Nullable HttpHeaders headers) { * @param headers the entity headers * @deprecated in favor of {@link #HttpEntity(HttpHeaders)} */ + @SuppressWarnings("NullAway") @Deprecated(since = "7.0", forRemoval = true) public HttpEntity(MultiValueMap headers) { this(null, headers); @@ -122,7 +125,7 @@ public HttpEntity(MultiValueMap headers) { * @deprecated in favor of {@link #HttpEntity(Object, HttpHeaders)} */ @Deprecated(since = "7.0", forRemoval = true) - public HttpEntity(@Nullable T body, @Nullable MultiValueMap headers) { + public HttpEntity(T body, @Nullable MultiValueMap headers) { this(body, (headers != null) ? new HttpHeaders(headers) : new HttpHeaders()); } @@ -137,7 +140,7 @@ public HttpHeaders getHeaders() { /** * Returns the body of this entity. */ - public @Nullable T getBody() { + public T getBody() { return this.body; } diff --git a/spring-web/src/main/java/org/springframework/http/RequestEntity.java b/spring-web/src/main/java/org/springframework/http/RequestEntity.java index 6812f3eb936c..870b878e1c2f 100644 --- a/spring-web/src/main/java/org/springframework/http/RequestEntity.java +++ b/spring-web/src/main/java/org/springframework/http/RequestEntity.java @@ -65,7 +65,7 @@ * @see org.springframework.web.client.RestOperations#exchange(RequestEntity, Class) * @see ResponseEntity */ -public class RequestEntity extends HttpEntity { +public class RequestEntity extends HttpEntity { private final @Nullable HttpMethod method; @@ -78,6 +78,7 @@ public class RequestEntity extends HttpEntity { * @param method the method * @param url the URL */ + @SuppressWarnings("NullAway") public RequestEntity(HttpMethod method, URI url) { this(null, (HttpHeaders) null, method, url, null); } @@ -88,7 +89,7 @@ public RequestEntity(HttpMethod method, URI url) { * @param method the method * @param url the URL */ - public RequestEntity(@Nullable T body, HttpMethod method, URI url) { + public RequestEntity(T body, HttpMethod method, URI url) { this(body, (HttpHeaders) null, method, url, null); } @@ -100,7 +101,7 @@ public RequestEntity(@Nullable T body, HttpMethod method, URI url) { * @param type the type used for generic type resolution * @since 4.3 */ - public RequestEntity(@Nullable T body, HttpMethod method, URI url, Type type) { + public RequestEntity(T body, HttpMethod method, URI url, Type type) { this(body, (HttpHeaders) null, method, url, type); } @@ -111,6 +112,7 @@ public RequestEntity(@Nullable T body, HttpMethod method, URI url, Type type) { * @param url the URL * @since 7.0 */ + @SuppressWarnings("NullAway") public RequestEntity(HttpHeaders headers, HttpMethod method, URI url) { this(null, headers, method, url, null); } @@ -123,7 +125,7 @@ public RequestEntity(HttpHeaders headers, HttpMethod method, URI url) { * @param url the URL * @since 7.0 */ - public RequestEntity(@Nullable T body, @Nullable HttpHeaders headers, + public RequestEntity(T body, @Nullable HttpHeaders headers, @Nullable HttpMethod method, URI url) { this(body, headers, method, url, null); @@ -138,7 +140,7 @@ public RequestEntity(@Nullable T body, @Nullable HttpHeaders headers, * @param type the type used for generic type resolution * @since 7.0 */ - public RequestEntity(@Nullable T body, @Nullable HttpHeaders headers, + public RequestEntity(T body, @Nullable HttpHeaders headers, @Nullable HttpMethod method, @Nullable URI url, @Nullable Type type) { super(body, headers); @@ -154,6 +156,7 @@ public RequestEntity(@Nullable T body, @Nullable HttpHeaders headers, * @param url the URL * @deprecated in favor of {@link #RequestEntity(HttpHeaders, HttpMethod, URI)} */ + @SuppressWarnings("NullAway") @Deprecated(since = "7.0", forRemoval = true) public RequestEntity(MultiValueMap headers, HttpMethod method, URI url) { this(null, headers, method, url, null); @@ -169,7 +172,7 @@ public RequestEntity(MultiValueMap headers, HttpMethod method, U */ @Deprecated(since = "7.0", forRemoval = true) public RequestEntity( - @Nullable T body, @Nullable MultiValueMap headers, + T body, @Nullable MultiValueMap headers, @Nullable HttpMethod method, URI url) { this(body, headers, method, url, null); @@ -187,7 +190,7 @@ public RequestEntity( */ @SuppressWarnings("removal") @Deprecated(since = "7.0", forRemoval = true) - public RequestEntity(@Nullable T body, @Nullable MultiValueMap headers, + public RequestEntity(T body, @Nullable MultiValueMap headers, @Nullable HttpMethod method, @Nullable URI url, @Nullable Type type) { super(body, headers); @@ -546,7 +549,7 @@ public interface HeadersBuilder> { * @return the request entity * @see BodyBuilder#body(Object) */ - RequestEntity build(); + RequestEntity<@Nullable Void> build(); } @@ -702,7 +705,7 @@ public BodyBuilder ifNoneMatch(String... ifNoneMatches) { } @Override - public RequestEntity build() { + public RequestEntity<@Nullable Void> build() { return buildInternal(null, null); } @@ -716,7 +719,7 @@ public RequestEntity body(T body, Type type) { return buildInternal(body, type); } - private RequestEntity buildInternal(@Nullable T body, @Nullable Type type) { + private RequestEntity buildInternal(T body, @Nullable Type type) { if (this.uri != null) { return new RequestEntity<>(body, this.headers, this.method, this.uri, type); } @@ -736,7 +739,7 @@ else if (this.uriTemplate != null){ * @since 5.3 * @param the body type */ - public static class UriTemplateRequestEntity extends RequestEntity { + public static class UriTemplateRequestEntity extends RequestEntity { private final String uriTemplate; @@ -745,7 +748,7 @@ public static class UriTemplateRequestEntity extends RequestEntity { private final @Nullable Map uriVarsMap; UriTemplateRequestEntity( - @Nullable T body, @Nullable HttpHeaders headers, + T body, @Nullable HttpHeaders headers, @Nullable HttpMethod method, @Nullable Type type, String uriTemplate, @Nullable Object @Nullable [] uriVarsArray, @Nullable Map uriVarsMap) { diff --git a/spring-web/src/main/java/org/springframework/http/ResponseEntity.java b/spring-web/src/main/java/org/springframework/http/ResponseEntity.java index 9d879cf55263..74329ea8bbaa 100644 --- a/spring-web/src/main/java/org/springframework/http/ResponseEntity.java +++ b/spring-web/src/main/java/org/springframework/http/ResponseEntity.java @@ -78,7 +78,7 @@ * @see org.springframework.web.client.RestOperations#getForEntity(URI, Class) * @see RequestEntity */ -public class ResponseEntity extends HttpEntity { +public class ResponseEntity extends HttpEntity { private final HttpStatusCode status; @@ -87,6 +87,7 @@ public class ResponseEntity extends HttpEntity { * Create a {@code ResponseEntity} with a status code only. * @param status the status code */ + @SuppressWarnings("NullAway") public ResponseEntity(HttpStatusCode status) { this(null, (HttpHeaders) null, status); } @@ -96,7 +97,7 @@ public ResponseEntity(HttpStatusCode status) { * @param body the entity body * @param status the status code */ - public ResponseEntity(@Nullable T body, HttpStatusCode status) { + public ResponseEntity(T body, HttpStatusCode status) { this(body, (HttpHeaders) null, status); } @@ -106,6 +107,7 @@ public ResponseEntity(@Nullable T body, HttpStatusCode status) { * @param status the status code * @since 7.0 */ + @SuppressWarnings("NullAway") public ResponseEntity(HttpHeaders headers, HttpStatusCode status) { this(null, headers, status); } @@ -117,7 +119,7 @@ public ResponseEntity(HttpHeaders headers, HttpStatusCode status) { * @param rawStatus the status code value * @since 7.0 */ - public ResponseEntity(@Nullable T body, @Nullable HttpHeaders headers, int rawStatus) { + public ResponseEntity(T body, @Nullable HttpHeaders headers, int rawStatus) { this(body, headers, HttpStatusCode.valueOf(rawStatus)); } @@ -128,7 +130,7 @@ public ResponseEntity(@Nullable T body, @Nullable HttpHeaders headers, int rawSt * @param statusCode the status code * @since 7.0 */ - public ResponseEntity(@Nullable T body, @Nullable HttpHeaders headers, HttpStatusCode statusCode) { + public ResponseEntity(T body, @Nullable HttpHeaders headers, HttpStatusCode statusCode) { super(body, headers); Assert.notNull(statusCode, "HttpStatusCode must not be null"); @@ -141,6 +143,7 @@ public ResponseEntity(@Nullable T body, @Nullable HttpHeaders headers, HttpStatu * @param status the status code * @deprecated in favor of {@link #ResponseEntity(HttpHeaders, HttpStatusCode)} */ + @SuppressWarnings("NullAway") @Deprecated(since = "7.0", forRemoval = true) public ResponseEntity(MultiValueMap headers, HttpStatusCode status) { this(null, headers, status); @@ -155,7 +158,7 @@ public ResponseEntity(MultiValueMap headers, HttpStatusCode stat * @deprecated in favor of {@link #ResponseEntity(Object, HttpHeaders, int)} */ @Deprecated(since = "7.0", forRemoval = true) - public ResponseEntity(@Nullable T body, @Nullable MultiValueMap headers, int rawStatus) { + public ResponseEntity(T body, @Nullable MultiValueMap headers, int rawStatus) { this(body, headers, HttpStatusCode.valueOf(rawStatus)); } @@ -168,7 +171,7 @@ public ResponseEntity(@Nullable T body, @Nullable MultiValueMap */ @SuppressWarnings("removal") @Deprecated(since = "7.0", forRemoval = true) - public ResponseEntity(@Nullable T body, @Nullable MultiValueMap headers, HttpStatusCode statusCode) { + public ResponseEntity(T body, @Nullable MultiValueMap headers, HttpStatusCode statusCode) { super(body, headers); Assert.notNull(statusCode, "HttpStatusCode must not be null"); @@ -261,7 +264,7 @@ public static BodyBuilder ok() { * @return the created {@code ResponseEntity} * @since 4.1 */ - public static ResponseEntity ok(@Nullable T body) { + public static ResponseEntity ok(T body) { return ok().body(body); } @@ -294,7 +297,7 @@ public static HeadersBuilder of(ProblemDetail body) { @SuppressWarnings("unchecked") @Override - public ResponseEntity build() { + public ResponseEntity build() { return (ResponseEntity) body(body); } }; @@ -308,7 +311,7 @@ public ResponseEntity build() { * @return the created {@code ResponseEntity} * @since 6.0.5 */ - public static ResponseEntity ofNullable(@Nullable T body) { + public static ResponseEntity ofNullable(@Nullable T body) { if (body == null) { return notFound().build(); } @@ -516,7 +519,7 @@ public interface HeadersBuilder> { * @return the response entity * @see BodyBuilder#body(Object) */ - ResponseEntity build(); + ResponseEntity build(); } @@ -550,7 +553,7 @@ public interface BodyBuilder extends HeadersBuilder { * @param body the body of the response entity * @return the built response entity */ - ResponseEntity body(@Nullable T body); + ResponseEntity body(T body); } @@ -652,13 +655,14 @@ public BodyBuilder varyBy(String... requestHeaders) { return this; } + @SuppressWarnings("NullAway") @Override - public ResponseEntity build() { + public ResponseEntity build() { return body(null); } @Override - public ResponseEntity body(@Nullable T body) { + public ResponseEntity body(T body) { return new ResponseEntity<>(body, this.headers, this.statusCode); } } diff --git a/spring-web/src/main/java/org/springframework/http/client/MultipartBodyBuilder.java b/spring-web/src/main/java/org/springframework/http/client/MultipartBodyBuilder.java index 318e12a1c53f..6a5cfe953785 100644 --- a/spring-web/src/main/java/org/springframework/http/client/MultipartBodyBuilder.java +++ b/spring-web/src/main/java/org/springframework/http/client/MultipartBodyBuilder.java @@ -317,7 +317,7 @@ private HttpHeaders initHeadersIfNecessary() { } public HttpEntity build() { - return new HttpEntity<>(this.body, this.headers); + return new HttpEntity<@Nullable Object>(this.body, this.headers); } } diff --git a/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java b/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java index 7b8558a51e30..01282d7d955e 100644 --- a/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java +++ b/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java @@ -1016,7 +1016,7 @@ private void logBody(Object body, @Nullable MediaType mediaType, HttpMessageConv /** * Response extractor for {@link HttpEntity}. */ - private class ResponseEntityResponseExtractor implements ResponseExtractor> { + private class ResponseEntityResponseExtractor implements ResponseExtractor> { private final @Nullable HttpMessageConverterExtractor delegate; @@ -1030,7 +1030,7 @@ public ResponseEntityResponseExtractor(@Nullable Type responseType) { } @Override - public ResponseEntity extractData(ClientHttpResponse response) throws IOException { + public ResponseEntity<@Nullable T> extractData(ClientHttpResponse response) throws IOException { if (this.delegate != null) { T body = this.delegate.extractData(response); return ResponseEntity.status(response.getStatusCode()).headers(response.getHeaders()).body(body); diff --git a/spring-web/src/test/kotlin/org/springframework/http/ResponseEntityKotlinTests.kt b/spring-web/src/test/kotlin/org/springframework/http/ResponseEntityKotlinTests.kt index cd90622f6998..64e6f3c0e92e 100644 --- a/spring-web/src/test/kotlin/org/springframework/http/ResponseEntityKotlinTests.kt +++ b/spring-web/src/test/kotlin/org/springframework/http/ResponseEntityKotlinTests.kt @@ -43,4 +43,52 @@ class ResponseEntityKotlinTests { assertThat(responseEntity.body).isNull() } + + @Test + fun ofNullNullableType() { + val responseEntity = ResponseEntity.ofNullable(null) + assertThat(responseEntity).isNotNull() + assertThat(responseEntity.statusCode).isEqualTo(HttpStatus.NOT_FOUND) + assertThat(responseEntity.body).isNull() + } + + @Test + fun okNullNullableType() { + val responseEntity = ResponseEntity.ok(null) + assertThat(responseEntity).isNotNull() + assertThat(responseEntity.statusCode).isEqualTo(HttpStatus.OK) + assertThat(responseEntity.body).isNull() + } + + @Test + fun okNullUnitType() { + val responseEntity = ResponseEntity.ok(null) + assertThat(responseEntity).isNotNull() + assertThat(responseEntity.statusCode).isEqualTo(HttpStatus.OK) + assertThat(responseEntity.body).isNull() + } + + @Test + fun okNullNullableUnitType() { + val responseEntity = ResponseEntity.ok(null) + assertThat(responseEntity).isNotNull() + assertThat(responseEntity.statusCode).isEqualTo(HttpStatus.OK) + assertThat(responseEntity.body).isNull() + } + + @Test + fun noContentUnitType() { + val responseEntity = ResponseEntity.noContent().build() + assertThat(responseEntity).isNotNull() + assertThat(responseEntity.statusCode).isEqualTo(HttpStatus.NO_CONTENT) + assertThat(responseEntity.body).isNull() + } + + @Test + fun noContentNullableUnitType() { + val responseEntity: ResponseEntity = ResponseEntity.noContent().build() + assertThat(responseEntity).isNotNull() + assertThat(responseEntity.statusCode).isEqualTo(HttpStatus.NO_CONTENT) + assertThat(responseEntity.body).isNull() + } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClientUtils.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClientUtils.java index 09765c3f72fb..398df34e364d 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClientUtils.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClientUtils.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.function.Predicate; +import org.jspecify.annotations.Nullable; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -54,7 +55,7 @@ abstract class WebClientUtils { @SuppressWarnings("unchecked") public static Mono> mapToEntity(ClientResponse response, Mono bodyMono) { return ((Mono) bodyMono).defaultIfEmpty(VALUE_NONE).map(body -> - new ResponseEntity<>( + new ResponseEntity<@Nullable T>( body != VALUE_NONE ? (T) body : null, response.headers().asHttpHeaders(), response.statusCode())); diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/HttpEntityMethodArgumentResolver.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/HttpEntityMethodArgumentResolver.java index ee90c221cf30..f8732d6325be 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/HttpEntityMethodArgumentResolver.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/HttpEntityMethodArgumentResolver.java @@ -63,8 +63,8 @@ public Mono resolveArgument( private Object createEntity(@Nullable Object body, Class entityType, ServerHttpRequest request) { return (RequestEntity.class.equals(entityType) ? - new RequestEntity<>(body, request.getHeaders(), request.getMethod(), request.getURI()) : - new HttpEntity<>(body, request.getHeaders())); + new RequestEntity<@Nullable Object>(body, request.getHeaders(), request.getMethod(), request.getURI()) : + new HttpEntity<@Nullable Object>(body, request.getHeaders())); } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityExceptionHandler.java b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityExceptionHandler.java index e65d04f01d70..21f9a233e319 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityExceptionHandler.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityExceptionHandler.java @@ -105,7 +105,7 @@ public void setMessageSource(MessageSource messageSource) { ErrorResponseException.class, MethodValidationException.class }) - public final Mono> handleException(Exception ex, ServerWebExchange exchange) { + public final Mono> handleException(Exception ex, ServerWebExchange exchange) { if (ex instanceof MethodNotAllowedException theEx) { return handleMethodNotAllowedException(theEx, theEx.getHeaders(), theEx.getStatusCode(), exchange); } @@ -159,7 +159,7 @@ else if (ex instanceof MethodValidationException theEx) { * @param exchange the current request and response * @return a {@code Mono} with the {@code ResponseEntity} for the response */ - protected Mono> handleMethodNotAllowedException( + protected Mono> handleMethodNotAllowedException( MethodNotAllowedException ex, HttpHeaders headers, HttpStatusCode status, ServerWebExchange exchange) { @@ -175,7 +175,7 @@ protected Mono> handleMethodNotAllowedException( * @param exchange the current request and response * @return a {@code Mono} with the {@code ResponseEntity} for the response */ - protected Mono> handleNotAcceptableStatusException( + protected Mono> handleNotAcceptableStatusException( NotAcceptableStatusException ex, HttpHeaders headers, HttpStatusCode status, ServerWebExchange exchange) { @@ -191,7 +191,7 @@ protected Mono> handleNotAcceptableStatusException( * @param exchange the current request and response * @return a {@code Mono} with the {@code ResponseEntity} for the response */ - protected Mono> handleUnsupportedMediaTypeStatusException( + protected Mono> handleUnsupportedMediaTypeStatusException( UnsupportedMediaTypeStatusException ex, HttpHeaders headers, HttpStatusCode status, ServerWebExchange exchange) { @@ -207,7 +207,7 @@ protected Mono> handleUnsupportedMediaTypeStatusException * @param exchange the current request and response * @return a {@code Mono} with the {@code ResponseEntity} for the response */ - protected Mono> handleMissingRequestValueException( + protected Mono> handleMissingRequestValueException( MissingRequestValueException ex, HttpHeaders headers, HttpStatusCode status, ServerWebExchange exchange) { @@ -223,7 +223,7 @@ protected Mono> handleMissingRequestValueException( * @param exchange the current request and response * @return a {@code Mono} with the {@code ResponseEntity} for the response */ - protected Mono> handleUnsatisfiedRequestParameterException( + protected Mono> handleUnsatisfiedRequestParameterException( UnsatisfiedRequestParameterException ex, HttpHeaders headers, HttpStatusCode status, ServerWebExchange exchange) { @@ -239,7 +239,7 @@ protected Mono> handleUnsatisfiedRequestParameterExceptio * @param exchange the current request and response * @return a {@code Mono} with the {@code ResponseEntity} for the response */ - protected Mono> handleWebExchangeBindException( + protected Mono> handleWebExchangeBindException( WebExchangeBindException ex, HttpHeaders headers, HttpStatusCode status, ServerWebExchange exchange) { @@ -256,7 +256,7 @@ protected Mono> handleWebExchangeBindException( * @return a {@code Mono} with the {@code ResponseEntity} for the response * @since 6.1 */ - protected Mono> handleHandlerMethodValidationException( + protected Mono> handleHandlerMethodValidationException( HandlerMethodValidationException ex, HttpHeaders headers, HttpStatusCode status, ServerWebExchange exchange) { @@ -272,7 +272,7 @@ protected Mono> handleHandlerMethodValidationException( * @param exchange the current request and response * @return a {@code Mono} with the {@code ResponseEntity} for the response */ - protected Mono> handleServerWebInputException( + protected Mono> handleServerWebInputException( ServerWebInputException ex, HttpHeaders headers, HttpStatusCode status, ServerWebExchange exchange) { @@ -288,7 +288,7 @@ protected Mono> handleServerWebInputException( * @param exchange the current request and response * @return a {@code Mono} with the {@code ResponseEntity} for the response */ - protected Mono> handleResponseStatusException( + protected Mono> handleResponseStatusException( ResponseStatusException ex, HttpHeaders headers, HttpStatusCode status, ServerWebExchange exchange) { @@ -304,7 +304,7 @@ protected Mono> handleResponseStatusException( * @param exchange the current request and response * @return a {@code Mono} with the {@code ResponseEntity} for the response */ - protected Mono> handleServerErrorException( + protected Mono> handleServerErrorException( ServerErrorException ex, HttpHeaders headers, HttpStatusCode status, ServerWebExchange exchange) { @@ -320,7 +320,7 @@ protected Mono> handleServerErrorException( * @param exchange the current request and response * @return a {@code Mono} with the {@code ResponseEntity} for the response */ - protected Mono> handleErrorResponseException( + protected Mono> handleErrorResponseException( ErrorResponseException ex, HttpHeaders headers, HttpStatusCode status, ServerWebExchange exchange) { @@ -336,7 +336,7 @@ protected Mono> handleErrorResponseException( * @return a {@code Mono} with the {@code ResponseEntity} for the response * @since 6.1 */ - protected Mono> handleMethodValidationException( + protected Mono> handleMethodValidationException( MethodValidationException ex, HttpStatus status, ServerWebExchange exchange) { ProblemDetail body = createProblemDetail(ex, status, "Validation failed", null, null, exchange); @@ -394,7 +394,7 @@ private static Locale getLocale(ServerWebExchange exchange) { * @param exchange the current request and response * @return a {@code Mono} with the {@code ResponseEntity} for the response */ - protected Mono> handleExceptionInternal( + protected Mono> handleExceptionInternal( Exception ex, @Nullable Object body, @Nullable HttpHeaders headers, HttpStatusCode status, ServerWebExchange exchange) { @@ -421,11 +421,11 @@ protected Mono> handleExceptionInternal( * @return a {@code Mono} with the created {@code ResponseEntity} * @since 6.0 */ - protected Mono> createResponseEntity( + protected Mono> createResponseEntity( @Nullable Object body, @Nullable HttpHeaders headers, HttpStatusCode status, ServerWebExchange exchange) { - return Mono.just(new ResponseEntity<>(body, headers, status)); + return Mono.just(new ResponseEntity<@Nullable Object>(body, headers, status)); } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java index ed86ade4da6e..b1217baa287a 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java @@ -156,11 +156,11 @@ public boolean supportsReturnType(MethodParameter returnType) { Object body = readWithMessageConverters(webRequest, parameter, paramType); if (RequestEntity.class == parameter.getParameterType()) { - return new RequestEntity<>(body, inputMessage.getHeaders(), + return new RequestEntity<@Nullable Object>(body, inputMessage.getHeaders(), inputMessage.getMethod(), inputMessage.getURI()); } else { - return new HttpEntity<>(body, inputMessage.getHeaders()); + return new HttpEntity<@Nullable Object>(body, inputMessage.getHeaders()); } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java index 9cb5a30e8bb4..f5b3393e1125 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.java @@ -135,7 +135,7 @@ public void setMessageSource(MessageSource messageSource) { MethodValidationException.class, AsyncRequestNotUsableException.class }) - public final @Nullable ResponseEntity handleException(Exception ex, WebRequest request) throws Exception { + public final @Nullable ResponseEntity<@Nullable Object> handleException(Exception ex, WebRequest request) throws Exception { if (ex instanceof HttpRequestMethodNotSupportedException subEx) { return handleHttpRequestMethodNotSupported(subEx, subEx.getHeaders(), subEx.getStatusCode(), request); } @@ -219,7 +219,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * @return a {@code ResponseEntity} for the response to use, possibly * {@code null} when the response is already committed */ - protected @Nullable ResponseEntity handleHttpRequestMethodNotSupported( + protected @Nullable ResponseEntity<@Nullable Object> handleHttpRequestMethodNotSupported( HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { pageNotFoundLogger.warn(ex.getMessage()); @@ -236,7 +236,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * @return a {@code ResponseEntity} for the response to use, possibly * {@code null} when the response is already committed */ - protected @Nullable ResponseEntity handleHttpMediaTypeNotSupported( + protected @Nullable ResponseEntity<@Nullable Object> handleHttpMediaTypeNotSupported( HttpMediaTypeNotSupportedException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); @@ -252,7 +252,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * @return a {@code ResponseEntity} for the response to use, possibly * {@code null} when the response is already committed */ - protected @Nullable ResponseEntity handleHttpMediaTypeNotAcceptable( + protected @Nullable ResponseEntity<@Nullable Object> handleHttpMediaTypeNotAcceptable( HttpMediaTypeNotAcceptableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); @@ -269,7 +269,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * {@code null} when the response is already committed * @since 4.2 */ - protected @Nullable ResponseEntity handleMissingPathVariable( + protected @Nullable ResponseEntity<@Nullable Object> handleMissingPathVariable( MissingPathVariableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); @@ -285,7 +285,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * @return a {@code ResponseEntity} for the response to use, possibly * {@code null} when the response is already committed */ - protected @Nullable ResponseEntity handleMissingServletRequestParameter( + protected @Nullable ResponseEntity<@Nullable Object> handleMissingServletRequestParameter( MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); @@ -301,7 +301,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * @return a {@code ResponseEntity} for the response to use, possibly * {@code null} when the response is already committed */ - protected @Nullable ResponseEntity handleMissingServletRequestPart( + protected @Nullable ResponseEntity<@Nullable Object> handleMissingServletRequestPart( MissingServletRequestPartException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); @@ -317,7 +317,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * @return a {@code ResponseEntity} for the response to use, possibly * {@code null} when the response is already committed */ - protected @Nullable ResponseEntity handleServletRequestBindingException( + protected @Nullable ResponseEntity<@Nullable Object> handleServletRequestBindingException( ServletRequestBindingException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); @@ -333,7 +333,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * @return a {@code ResponseEntity} for the response to use, possibly * {@code null} when the response is already committed */ - protected @Nullable ResponseEntity handleMethodArgumentNotValid( + protected @Nullable ResponseEntity<@Nullable Object> handleMethodArgumentNotValid( MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); @@ -350,7 +350,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * {@code null} when the response is already committed * @since 6.1 */ - protected @Nullable ResponseEntity handleHandlerMethodValidationException( + protected @Nullable ResponseEntity<@Nullable Object> handleHandlerMethodValidationException( HandlerMethodValidationException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); @@ -367,7 +367,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * {@code null} when the response is already committed * @since 4.0 */ - protected @Nullable ResponseEntity handleNoHandlerFoundException( + protected @Nullable ResponseEntity<@Nullable Object> handleNoHandlerFoundException( NoHandlerFoundException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); @@ -384,7 +384,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * {@code null} when the response is already committed * @since 6.1 */ - protected @Nullable ResponseEntity handleNoResourceFoundException( + protected @Nullable ResponseEntity<@Nullable Object> handleNoResourceFoundException( NoResourceFoundException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); @@ -401,7 +401,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * {@code null} when the response is already committed * @since 4.2.8 */ - protected @Nullable ResponseEntity handleAsyncRequestTimeoutException( + protected @Nullable ResponseEntity<@Nullable Object> handleAsyncRequestTimeoutException( AsyncRequestTimeoutException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); @@ -418,7 +418,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * {@code null} when the response is already committed * @since 6.0 */ - protected @Nullable ResponseEntity handleErrorResponseException( + protected @Nullable ResponseEntity<@Nullable Object> handleErrorResponseException( ErrorResponseException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); @@ -435,7 +435,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * {@code null} when the response is already committed * @since 6.1 */ - protected @Nullable ResponseEntity handleMaxUploadSizeExceededException( + protected @Nullable ResponseEntity<@Nullable Object> handleMaxUploadSizeExceededException( MaxUploadSizeExceededException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { return handleExceptionInternal(ex, null, headers, status, request); @@ -454,7 +454,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * @return a {@code ResponseEntity} for the response to use, possibly * {@code null} when the response is already committed */ - protected @Nullable ResponseEntity handleConversionNotSupported( + protected @Nullable ResponseEntity<@Nullable Object> handleConversionNotSupported( ConversionNotSupportedException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { Object[] args = {ex.getPropertyName(), ex.getValue()}; @@ -477,7 +477,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * @return a {@code ResponseEntity} for the response to use, possibly * {@code null} when the response is already committed */ - protected @Nullable ResponseEntity handleTypeMismatch( + protected @Nullable ResponseEntity<@Nullable Object> handleTypeMismatch( TypeMismatchException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { Object[] args = {ex.getPropertyName(), ex.getValue(), @@ -502,7 +502,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * @return a {@code ResponseEntity} for the response to use, possibly * {@code null} when the response is already committed */ - protected @Nullable ResponseEntity handleHttpMessageNotReadable( + protected @Nullable ResponseEntity<@Nullable Object> handleHttpMessageNotReadable( HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { ProblemDetail body = createProblemDetail(ex, status, "Failed to read request", null, null, request); @@ -522,7 +522,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * @return a {@code ResponseEntity} for the response to use, possibly * {@code null} when the response is already committed */ - protected @Nullable ResponseEntity handleHttpMessageNotWritable( + protected @Nullable ResponseEntity<@Nullable Object> handleHttpMessageNotWritable( HttpMessageNotWritableException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) { ProblemDetail body = createProblemDetail(ex, status, "Failed to write request", null, null, request); @@ -543,7 +543,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * {@code null} when the response is already committed * @since 6.1 */ - protected @Nullable ResponseEntity handleMethodValidationException( + protected @Nullable ResponseEntity<@Nullable Object> handleMethodValidationException( MethodValidationException ex, HttpHeaders headers, HttpStatus status, WebRequest request) { ProblemDetail body = createProblemDetail(ex, status, "Validation failed", null, null, request); @@ -559,7 +559,7 @@ else if (ex instanceof AsyncRequestNotUsableException theEx) { * {@code null} when the response is already committed * @since 6.2 */ - protected @Nullable ResponseEntity handleAsyncRequestNotUsableException( + protected @Nullable ResponseEntity<@Nullable Object> handleAsyncRequestNotUsableException( AsyncRequestNotUsableException ex, WebRequest request) { return null; @@ -614,7 +614,7 @@ protected ProblemDetail createProblemDetail( * @return a {@code ResponseEntity} for the response to use, possibly * {@code null} when the response is already committed */ - protected @Nullable ResponseEntity handleExceptionInternal( + protected @Nullable ResponseEntity<@Nullable Object> handleExceptionInternal( Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatusCode statusCode, WebRequest request) { if (request instanceof ServletWebRequest servletWebRequest) { @@ -650,10 +650,10 @@ protected ProblemDetail createProblemDetail( * @return the {@code ResponseEntity} instance to use * @since 6.0 */ - protected ResponseEntity createResponseEntity( + protected ResponseEntity<@Nullable Object> createResponseEntity( @Nullable Object body, HttpHeaders headers, HttpStatusCode statusCode, WebRequest request) { - return new ResponseEntity<>(body, headers, statusCode); + return new ResponseEntity<@Nullable Object>(body, headers, statusCode); } }