From ed822390d88c4b91ed461fc7c2b3716e3cc6576b Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Mon, 28 Mar 2022 16:50:34 +0200 Subject: [PATCH] Fix potential NullPointerException in HalFormsAdaptingResponseBodyAdvice. Fixes #2123. --- .../config/HalFormsAdaptingResponseBodyAdvice.java | 5 +++-- .../HalFormsAdaptingResponseBodyAdviceTests.java | 12 +++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/HalFormsAdaptingResponseBodyAdvice.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/HalFormsAdaptingResponseBodyAdvice.java index 0cb2813d6..7f1f756d1 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/HalFormsAdaptingResponseBodyAdvice.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/HalFormsAdaptingResponseBodyAdvice.java @@ -30,6 +30,7 @@ import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; +import org.springframework.lang.Nullable; import org.springframework.web.HttpMediaTypeNotAcceptableException; import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; @@ -55,7 +56,7 @@ class HalFormsAdaptingResponseBodyAdvice> @Override @SneakyThrows - public RepresentationModel beforeBodyWrite(RepresentationModel body, MethodParameter returnType, + public RepresentationModel beforeBodyWrite(@Nullable RepresentationModel body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { @@ -66,7 +67,7 @@ class HalFormsAdaptingResponseBodyAdvice> List accept = request.getHeaders().getAccept(); - boolean hasAffordances = body.getLinks().stream() + boolean hasAffordances = body != null && body.getLinks().stream() .anyMatch(it -> !it.getAffordances().isEmpty()); // Affordances registered -> we're fine as we will render templates diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/config/HalFormsAdaptingResponseBodyAdviceTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/config/HalFormsAdaptingResponseBodyAdviceTests.java index 32c7fd41a..d5a745a58 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/config/HalFormsAdaptingResponseBodyAdviceTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/config/HalFormsAdaptingResponseBodyAdviceTests.java @@ -35,6 +35,7 @@ import org.springframework.http.MediaType; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.http.server.ServletServerHttpResponse; +import org.springframework.lang.Nullable; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.web.HttpMediaTypeNotAcceptableException; @@ -95,7 +96,16 @@ class HalFormsAdaptingResponseBodyAdviceTests> .isThrownBy(() -> assertResponseContentType(model, MediaTypes.HAL_JSON)); } - private void assertResponseContentType(RepresentationModel model, MediaType mediaType) { + @Test // #2123 + void handlesNullBodyCorrectly() { + + request.addHeader(HttpHeaders.ACCEPT, + MediaType.toString(Arrays.asList(MediaTypes.HAL_JSON))); + + assertThatNoException().isThrownBy(() -> assertResponseContentType(null, MediaTypes.HAL_JSON)); + } + + private void assertResponseContentType(@Nullable RepresentationModel model, MediaType mediaType) { this.response.addHeader(HttpHeaders.CONTENT_TYPE, MediaTypes.HAL_FORMS_JSON_VALUE); ServletServerHttpResponse response = new ServletServerHttpResponse(this.response);