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

@@ -222,6 +222,36 @@ class RequestMappingHandlerMappingTests {
);
}
@Test // gh-32065
void httpExchangeAnnotationsOverriddenAtClassLevel() throws NoSuchMethodException {
this.handlerMapping.afterPropertiesSet();
Class<?> controllerClass = ClassLevelOverriddenHttpExchangeAnnotationsController.class;
Method method = controllerClass.getDeclaredMethod("post");
RequestMappingInfo info = this.handlerMapping.getMappingForMethod(method, controllerClass);
assertThat(info).isNotNull();
assertThat(info.getPatternsCondition()).isNotNull();
assertThat(info.getPatternsCondition().getPatterns()).extracting(PathPattern::getPatternString)
.containsOnly("/controller/postExchange");
}
@Test // gh-32065
void httpExchangeAnnotationsOverriddenAtMethodLevel() throws NoSuchMethodException {
this.handlerMapping.afterPropertiesSet();
Class<?> controllerClass = MethodLevelOverriddenHttpExchangeAnnotationsController.class;
Method method = controllerClass.getDeclaredMethod("post");
RequestMappingInfo info = this.handlerMapping.getMappingForMethod(method, controllerClass);
assertThat(info).isNotNull();
assertThat(info.getPatternsCondition()).isNotNull();
assertThat(info.getPatternsCondition().getPatterns()).extracting(PathPattern::getPatternString)
.containsOnly("/controller/postMapping");
}
@SuppressWarnings("DataFlowIssue")
@Test
void httpExchangeWithDefaultValues() throws NoSuchMethodException {
@@ -417,6 +447,33 @@ class RequestMappingHandlerMappingTests {
void post() {}
}
@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)