Skip to content

PathVariable resolution does not work properly [SPR-6280] #10947

@spring-projects-issues

Description

@spring-projects-issues

Tomas Vojtech opened SPR-6280 and commented

For controller

@Controller
@RequestMapping("/category")
public class CategoryController extends AbstractCsController {

    @Autowired
    private ICraftService craftService;

    @RequestMapping(value = {"/{category}/page/{page}", "/**/{category}/page/{page}"})
    public String category(@PathVariable String category, @PathVariable int page, Model model) {
        model.addAttribute("categories", craftService.findSubcategories(category));
        return "craft/category";
    }

    @RequestMapping(value = {"/{category}", "/**/{category}"})
    public String category(@PathVariable String category, Model model) {
        return category(category, 1, model);
    }

    @RequestMapping(value = {""})
    public String category(Model model) {
        return category(1, model);
    }

    @RequestMapping(value = {"/page/{page}"})
    public String category(@PathVariable int page, Model model) {
        return category(null, page, model);
    }

}

I get following error for url like localhost:8080/context/category/page/5

org.springframework.web.bind.annotation.support.HandlerMethodInvocationException: Failed to invoke handler method [public java.lang.String net.tv.cs.craft.controller.CategoryController.category(int,org.springframework.ui.Model)]; nested exception is java.lang.IllegalStateException: Could not find @PathVariable [page] in @RequestMapping
	at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:164)
	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:378)
	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:366)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:781)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:726)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:636)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:545)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
	at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1093)
	at com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:125)
	at com.opensymphony.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:76)
	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
	at org.springframework.web.filter.ShallowEtagHeaderFilter.doFilterInternal(ShallowEtagHeaderFilter.java:57)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
	at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
	at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
	at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
	at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:726)
	at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
	at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:206)
	at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
	at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
	at org.mortbay.jetty.Server.handle(Server.java:324)
	at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
	at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:829)
	at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:514)
	at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
	at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
	at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
	at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
Caused by: java.lang.IllegalStateException: Could not find @PathVariable [page] in @RequestMapping
	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.resolvePathVariable(AnnotationMethodHandlerAdapter.java:660)
	at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolvePathVariable(HandlerMethodInvoker.java:542)
	at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:282)
	at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:156)
	... 35 more

Problem seems to be in AbstractUrlHandlerMapping.lookupHandler. MAybe in code:

// Pattern match?
String bestPathMatch = null;
for (String registeredPath : this.handlerMap.keySet()) {
	if (getPathMatcher().match(registeredPath, urlPath) &&
		(bestPathMatch == null || bestPathMatch.length() < registeredPath.length())) {
		bestPathMatch = registeredPath;
	}
}

After ending this loop the bestPathMatch variable has value /category/**/{category}/ but it should have /category/page/{page}. Because of this code ```java
Map<String, String> uriTemplateVariables = getPathMatcher().extractUriTemplateVariables(bestPathMatch, urlPath);

```category -> 5
``` entry, but should 
```page -> 5
```. Because of the *uriTemplateVariables* doesn't contain the _page_ key it ends with the exception.

I think it is a bug because it resolves method handler correctly but the parameter resolution is not correct.

Affects: 3.0 RC1

Issue Links:

Referenced from: commits ef50082

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)type: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions