Reject mixed @⁠RequestMapping and @⁠HttpExchange declarations in MVC & WebFlux

This commit updates the RequestMappingHandlerMapping implementations in
Spring MVC and Spring WebFlux so that mixed @⁠RequestMapping and
@⁠HttpExchange declarations on the same element are rejected.

Note, however, that a @⁠Controller class which implements an interface
annotated with @⁠HttpExchange annotations can still inherit the
@⁠HttpExchange declarations from the interface or optionally override
them locally with @⁠HttpExchange or @⁠RequestMapping annotations.

See gh-31962
See gh-32049
Closes gh-32065
This commit is contained in:
Sam Brannen
2024-01-19 16:23:37 +01:00
parent c820e44a99
commit 6697461003
4 changed files with 124 additions and 6 deletions

View File

@@ -310,6 +310,40 @@ class RequestMappingHandlerMappingTests {
);
}
@Test // gh-32065
void httpExchangeWithMixedAnnotationsAtClassLevel() throws NoSuchMethodException {
RequestMappingHandlerMapping mapping = createMapping();
Class<?> controllerClass = MixedClassLevelAnnotationsController.class;
Method method = controllerClass.getDeclaredMethod("post");
assertThatIllegalStateException()
.isThrownBy(() -> mapping.getMappingForMethod(method, controllerClass))
.withMessageContainingAll(
controllerClass.getName(),
"is annotated with @RequestMapping and @HttpExchange annotations, but only one is allowed:",
"@" + RequestMapping.class.getName(),
"@" + HttpExchange.class.getName()
);
}
@Test // gh-32065
void httpExchangeWithMixedAnnotationsAtMethodLevel() throws NoSuchMethodException {
RequestMappingHandlerMapping mapping = createMapping();
Class<?> controllerClass = MixedMethodLevelAnnotationsController.class;
Method method = controllerClass.getDeclaredMethod("post");
assertThatIllegalStateException()
.isThrownBy(() -> mapping.getMappingForMethod(method, controllerClass))
.withMessageContainingAll(
method.toString(),
"is annotated with @RequestMapping and @HttpExchange annotations, but only one is allowed:",
"@" + PostMapping.class.getName(),
"@" + PostExchange.class.getName()
);
}
@SuppressWarnings("DataFlowIssue")
@Test
void httpExchangeWithDefaultValues() throws NoSuchMethodException {
@@ -488,6 +522,26 @@ class RequestMappingHandlerMappingTests {
}
@Controller
@RequestMapping("/api")
@HttpExchange("/api")
static class MixedClassLevelAnnotationsController {
@PostExchange("/post")
void post() {}
}
@Controller
@RequestMapping("/api")
static class MixedMethodLevelAnnotationsController {
@PostMapping("/post")
@PostExchange("/post")
void post() {}
}
@HttpExchange
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)