-
Notifications
You must be signed in to change notification settings - Fork 38.5k
Wrong warning logged for multiple @RequestMapping
annotations
#33387
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I was not able to reproduce this, and the logs don't seem entirely consistent with the snippet. Please provide a fuller reproducer (additionally specifying the exact version that you are using). |
@PatchMapping
annotations
@PatchMapping
annotations@RequestMapping
annotations
I see what the logging caused now (updated comment above and also attached sample project): I have a "common" annotation that defines many defaults for all implementing @RestController classes. So they can use the But in case a controller has to override some of those definitions, then the class has But still the warning is wrong in this special case, as both my endpoints are reachable. |
Hi @membersound, Thanks for the feedback.
I edited your updated comment, but due to an issue with caching in the browser, the link to your attached sample project got deleted, and I don't know how to reintroduce the link to that attachment. So, I apologize for that.
I think I understand what you are trying to convey now; however, In addition, In any case, annotating Is that perhaps the scenario you encountered?
Assuming you meant a setup similar to the following, yes, I agree that the warning can be potentially confusing. package example;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
@SpringJUnitWebConfig
class ControllerTests {
@Test
void test(WebApplicationContext wac) throws Exception {
MockMvc mockMvc = webAppContextSetup(wac).build();
mockMvc.perform(get("/rest").param("version", "1"))
.andExpectAll(
status().isOk(),
content().string("version1"));
mockMvc.perform(get("/rest").param("version", "2"))
.andExpectAll(
status().isOk(),
content().string("version2"));
}
@Configuration
@EnableWebMvc
@Import(ExampleController.class)
static class Config {
}
@ControllerDefaults
@RequestMapping("/rest")
public static class ExampleController {
@GetMapping(params = "version=1")
public String v1() {
return "version1";
}
@GetMapping(params = "version=2")
public String v2() {
return "version2";
}
}
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@RestController
@RequestMapping(path = "/default",
produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_PLAIN_VALUE },
consumes = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
public @interface ControllerDefaults {
}
} When I run that test class, I see the following log output.
However, as I stated in #31962 (comment):
Thus, I can see how one might expect that the locally declared We'll see if we can improve this. |
If your actual scenario is analogous to the example I provided above, the warning is technically correct in that the local In any case, can you please confirm that your use case is analogous to the Thanks |
You perfectly reproduced my issue. Thanks a lot. So you are saying, the warning is correct because the local So far I thought the warning message was about the endpoints that are accessible under the same path. But it seems the complain is more about the mapping annotations then. |
Glad we were able to sort that out.
You're welcome.
Yes, the warning is technically correct. The directly present
The warning is about potentially competing/conflicting In any case, as I mentioned above, although the warning is technically correct, I can see how it can be misleading since a directly present Thus, we may choose to avoid logging a warning in such cases, and we'll discuss this within the team. |
After discussing this within the team, we decided to leave the warning as-is based on the following rationale.
For example, @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RestController
@RequestMapping
public @interface DefaultsRestController {
@AliasFor(annotation = RequestMapping.class)
String[] path() default "/default";
@AliasFor(annotation = RequestMapping.class)
String[] consumes() default { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE };
@AliasFor(annotation = RequestMapping.class)
String[] produces() default { MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_PLAIN_VALUE };
@AliasFor(annotation = RequestMapping.class)
String[] params() default {};
@AliasFor(annotation = RequestMapping.class)
String[] headers() default {};
} The @DefaultsRestController(path = "/rest", consumes = MediaType.TEXT_PLAIN_VALUE)
public class ExampleController {
// ... And the test can be revised as follows, specifying the content type. @Test
void test(WebApplicationContext wac) throws Exception {
MockMvc mockMvc = webAppContextSetup(wac).build();
mockMvc.perform(get("/rest")
.contentType(MediaType.TEXT_PLAIN)
.param("version", "1"))
.andExpectAll(
status().isOk(),
content().string("version1"));
mockMvc.perform(get("/rest")
.contentType(MediaType.TEXT_PLAIN)
.param("version", "2"))
.andExpectAll(
status().isOk(),
content().string("version2"));
} The combination of the above achieves what we believe were the original goals of the In light of that, I am closing this issue. |
Thanks for the detailed feedback. I can fully relate to the explaination and will follow your suggestions to rewrite our code. Thanks for your time! |
Uh oh!
There was an error while loading. Please reload this page.
The following creates a false log warning message:
Result on startup:
Which is wrong, because both endpoints are working correctly and can be accessed using:
localhost:8080/rest?version=1
orlocalhost:8080/rest?version=2
.This the change that introduced the problem: #31962
Probably the implementation simply forgot to evaluate if different params are set on the mappings.
The text was updated successfully, but these errors were encountered: