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
This commit is contained in:
Oliver Drotbohm
2025-05-20 14:34:09 +02:00
parent 5e6d920499
commit 858b818f2f
2 changed files with 36 additions and 1 deletions

View File

@@ -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);
}
}

View File

@@ -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) {}
}
}