Ensure inherited @⁠HttpExchange annotation can be overridden in controller

This commit revises the RequestMappingHandlerMapping implementations in
Spring MVC and Spring WebFlux to ensure that a @⁠Controller class which
implements an interface annotated with @⁠HttpExchange annotations can
inherit the @⁠HttpExchange declarations from the interface or
optionally override them locally with @⁠HttpExchange or
@⁠RequestMapping annotations.

Closes gh-32065
This commit is contained in:
Sam Brannen
2024-01-19 18:54:31 +01:00
parent 17cef18760
commit 4cc91a2869
4 changed files with 157 additions and 32 deletions

View File

@@ -344,6 +344,48 @@ class RequestMappingHandlerMappingTests {
);
}
@Test // gh-32065
void httpExchangeAnnotationsOverriddenAtClassLevel() throws NoSuchMethodException {
RequestMappingHandlerMapping mapping = createMapping();
Class<?> controllerClass = ClassLevelOverriddenHttpExchangeAnnotationsController.class;
Method method = controllerClass.getDeclaredMethod("post");
RequestMappingInfo info = mapping.getMappingForMethod(method, controllerClass);
assertThat(info).isNotNull();
assertThat(info.getActivePatternsCondition()).isNotNull();
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/service/postExchange");
initRequestPath(mapping, request);
assertThat(info.getActivePatternsCondition().getMatchingCondition(request)).isNull();
request = new MockHttpServletRequest("POST", "/controller/postExchange");
initRequestPath(mapping, request);
assertThat(info.getActivePatternsCondition().getMatchingCondition(request)).isNotNull();
}
@Test // gh-32065
void httpExchangeAnnotationsOverriddenAtMethodLevel() throws NoSuchMethodException {
RequestMappingHandlerMapping mapping = createMapping();
Class<?> controllerClass = MethodLevelOverriddenHttpExchangeAnnotationsController.class;
Method method = controllerClass.getDeclaredMethod("post");
RequestMappingInfo info = mapping.getMappingForMethod(method, controllerClass);
assertThat(info).isNotNull();
assertThat(info.getActivePatternsCondition()).isNotNull();
MockHttpServletRequest request = new MockHttpServletRequest("POST", "/service/postExchange");
initRequestPath(mapping, request);
assertThat(info.getActivePatternsCondition().getMatchingCondition(request)).isNull();
request = new MockHttpServletRequest("POST", "/controller/postMapping");
initRequestPath(mapping, request);
assertThat(info.getActivePatternsCondition().getMatchingCondition(request)).isNotNull();
}
@SuppressWarnings("DataFlowIssue")
@Test
void httpExchangeWithDefaultValues() throws NoSuchMethodException {
@@ -542,6 +584,34 @@ class RequestMappingHandlerMappingTests {
}
@HttpExchange("/service")
interface Service {
@PostExchange("/postExchange")
void post();
}
@Controller
@RequestMapping("/controller")
static class ClassLevelOverriddenHttpExchangeAnnotationsController implements Service {
@Override
public void post() {}
}
@Controller
@RequestMapping("/controller")
static class MethodLevelOverriddenHttpExchangeAnnotationsController implements Service {
@PostMapping("/postMapping")
@Override
public void post() {}
}
@HttpExchange
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)