From 858b818f2ff53dbeb90e81df9c86b888e6c76bbd Mon Sep 17 00:00:00 2001 From: Oliver Drotbohm Date: Tue, 20 May 2025 14:34:09 +0200 Subject: [PATCH] Failure to look up repository metadata is now rejected with a 404 Not Found. We now produce an HttpClientErrorException if ResourceMetadataHandlerMethodArgumentResolver fails for find metadata for a parsed repository key so that it automatically results in a 404 Not Found status code over a previous 500 Internal Server Error. Fixes GH-2480 --- ...MetadataHandlerMethodArgumentResolver.java | 4 ++- ...andlerMethodArgumentResolverUnitTests.java | 33 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/ResourceMetadataHandlerMethodArgumentResolver.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/ResourceMetadataHandlerMethodArgumentResolver.java index 775b7baf2..81afaecf6 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/ResourceMetadataHandlerMethodArgumentResolver.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/ResourceMetadataHandlerMethodArgumentResolver.java @@ -24,8 +24,10 @@ import org.springframework.data.rest.core.mapping.ResourceMappings; import org.springframework.data.rest.core.mapping.ResourceMetadata; import org.springframework.data.rest.webmvc.BaseUri; import org.springframework.data.rest.webmvc.util.UriUtils; +import org.springframework.http.HttpStatus; import org.springframework.util.Assert; import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; @@ -86,6 +88,6 @@ public class ResourceMetadataHandlerMethodArgumentResolver implements HandlerMet } } - throw new IllegalArgumentException(String.format("Could not resolve repository metadata for %s.", repositoryKey)); + throw new HttpClientErrorException(HttpStatus.NOT_FOUND); } } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/config/ResourceMetadataHandlerMethodArgumentResolverUnitTests.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/config/ResourceMetadataHandlerMethodArgumentResolverUnitTests.java index dcbef33ec..0ef3766fc 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/config/ResourceMetadataHandlerMethodArgumentResolverUnitTests.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/webmvc/config/ResourceMetadataHandlerMethodArgumentResolverUnitTests.java @@ -19,12 +19,20 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.core.MethodParameter; import org.springframework.data.repository.support.Repositories; import org.springframework.data.rest.core.mapping.ResourceMappings; import org.springframework.data.rest.core.mapping.ResourceMetadata; import org.springframework.data.rest.webmvc.BaseUri; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; +import org.springframework.web.bind.support.DefaultDataBinderFactory; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; /** * Unit tests for {@link ResourceMetadataHandlerMethodArgumentResolver}. @@ -44,4 +52,29 @@ class ResourceMetadataHandlerMethodArgumentResolverUnitTests { assertThat(resolver.supportsParameter(parameter)).isTrue(); } + + @Test // GH-2480 + void failedMetadataLookupResultsInNotFound() throws Exception { + + var repositories = new Repositories(new DefaultListableBeanFactory()); + + var resolver = new ResourceMetadataHandlerMethodArgumentResolver(repositories, + mock(ResourceMappings.class), BaseUri.NONE); + + var method = SampleController.class.getDeclaredMethod("method", ResourceMappings.class); + var parameter = new MethodParameter(method, 0); + + var request = new MockHttpServletRequest(); + request.setRequestURI("/some/foo"); + + assertThatExceptionOfType(HttpClientErrorException.class).isThrownBy( + () -> resolver.resolveArgument(parameter, new ModelAndViewContainer(), new ServletWebRequest(request), + new DefaultDataBinderFactory(new ConfigurableWebBindingInitializer()))); + } + + static class SampleController { + + @GetMapping("/some/{repository}") + void method(ResourceMappings mappings) {} + } }