Skip to content

Commit

Permalink
Improve Error Message
Browse files Browse the repository at this point in the history
Closes gh-13667
  • Loading branch information
jzheaux committed Aug 21, 2023
1 parent ed96e2c commit 28f98b3
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 4 deletions.
Expand Up @@ -18,6 +18,7 @@

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -320,14 +321,17 @@ public C requestMatchers(HttpMethod method, String... patterns) {
if (!hasDispatcherServlet(registrations)) {
return requestMatchers(RequestMatchers.antMatchersAsArray(method, patterns));
}
Assert.isTrue(registrations.size() == 1,
"This method cannot decide whether these patterns are Spring MVC patterns or not. If this endpoint is a Spring MVC endpoint, please use requestMatchers(MvcRequestMatcher); otherwise, please use requestMatchers(AntPathRequestMatcher).");
if (registrations.size() > 1) {
String errorMessage = computeErrorMessage(registrations.values());
throw new IllegalArgumentException(errorMessage);
}
return requestMatchers(createMvcMatchers(method, patterns).toArray(new RequestMatcher[0]));
}

private Map<String, ? extends ServletRegistration> mappableServletRegistrations(ServletContext servletContext) {
Map<String, ServletRegistration> mappable = new LinkedHashMap<>();
for (Map.Entry<String, ? extends ServletRegistration> entry : servletContext.getServletRegistrations().entrySet()) {
for (Map.Entry<String, ? extends ServletRegistration> entry : servletContext.getServletRegistrations()
.entrySet()) {
if (!entry.getValue().getMappings().isEmpty()) {
mappable.put(entry.getKey(), entry.getValue());
}
Expand Down Expand Up @@ -355,6 +359,19 @@ private boolean hasDispatcherServlet(Map<String, ? extends ServletRegistration>
return false;
}

private String computeErrorMessage(Collection<? extends ServletRegistration> registrations) {
String template = "This method cannot decide whether these patterns are Spring MVC patterns or not. "
+ "If this endpoint is a Spring MVC endpoint, please use requestMatchers(MvcRequestMatcher); "
+ "otherwise, please use requestMatchers(AntPathRequestMatcher).\n\n"
+ "This is because there is more than one mappable servlet in your servlet context: %s.\n\n"
+ "For each MvcRequestMatcher, call MvcRequestMatcher#setServletPath to indicate the servlet path.";
Map<String, Collection<String>> mappings = new LinkedHashMap<>();
for (ServletRegistration registration : registrations) {
mappings.put(registration.getClassName(), registration.getMappings());
}
return String.format(template, mappings);
}

/**
* <p>
* If the {@link HandlerMappingIntrospector} is available in the classpath, maps to an
Expand Down
Expand Up @@ -63,12 +63,13 @@ public <O> O postProcess(O object) {
private WebApplicationContext context;

@BeforeEach
public void setUp() {
public void setUp() throws Exception {
this.matcherRegistry = new TestRequestMatcherRegistry();
this.context = mock(WebApplicationContext.class);
given(this.context.getBean(ObjectPostProcessor.class)).willReturn(NO_OP_OBJECT_POST_PROCESSOR);
given(this.context.getServletContext()).willReturn(MockServletContext.mvc());
this.matcherRegistry.setApplicationContext(this.context);
mockMvcPresentClasspath(true);
}

@Test
Expand Down Expand Up @@ -219,6 +220,7 @@ public void requestMatchersWhenAmbiguousServletsThenException() {

@Test
public void requestMatchersWhenUnmappableServletsThenSkips() {
mockMvcIntrospector(true);
MockServletContext servletContext = new MockServletContext();
given(this.context.getServletContext()).willReturn(servletContext);
servletContext.addServlet("dispatcherServlet", DispatcherServlet.class).addMapping("/");
Expand Down

0 comments on commit 28f98b3

Please sign in to comment.