Spring multiple path variables
Solution 1
This may be a bug (fixed in Spring 4.1): check out SPR-6741.
As described in the issue, you have in the same controller:
- a mapping with 3 path variables
- a "fallback" mapping
/**
Solution 2
Try this. Don't forget the ("lang")
in the path variable declaration in your method parameter
@RequestMapping(value = "/{lang}/{count}/{term}", method=RequestMethod.GET)
public ResponseEntity<?> getSomething(@PathVariable("lang") String lang, @PathVariable("count") String count, @PathVariable("term") String term) {
Admin
Updated on May 10, 2020Comments
-
Admin about 4 years
In my Spring controller, I try to get 3 path variables:
@RequestMapping("{language}/{country}/{term}/catalogue") - @PathVariable String language, @PathVariable String country, @PathVariable String term
Unfortunately this will not be recognized by the servlet.
There are ways to bind the URI, e.g.
@RequestMapping("**/catalogue")
and also@RequestMapping("{language}/{country}/catalogue")
will work, but with a third path variable the it stops working.The controller itself is also mapped to a specific path.
Is there a limit for path variables? Is it possible that other wildcards (e.g.
@RequestMapping("**"))
will be higher evaluated? e.g. 2 wildcards more specific than 3 defined values. But wildcards should be the last matching option in praxis.Regarding the appearing error:
First, with the wildcard mappings, they will be matched. When I disable the wildcard mappings aorg.springframework.web.HttpRequestMethodNotSupportedException
error is thrown.15:42:53,881 DEBUG [http-bio-18091-exec-31] (org.springframework.web.servlet.DispatcherServlet) - Handler execution resulted in exception - forwarding to resolved error view: ModelAndView: reference to view with name 'errors/exception'; model is null org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodResolver.resolveHandlerMethod(AnnotationMethodHandlerAdapter.java:665) at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:431) at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778) at javax.servlet.http.HttpServlet.service(HttpServlet.java:621) at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at [device detection filter] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:722)
The Controller method:
@RequestMapping(value = "{language}/{country}/{term}/catalogue", method = RequestMethod.GET) public ModelAndView catalogue(HttpServletRequest request, HttpServletResponse response, @PathVariable("language") String language, @PathVariable("country") String country, @PathVariable("term") String term, @RequestParam(value = "d", defaultValue = "") String device, @RequestParam(value = "embedded", defaultValue = "false") String embedded, @RequestParam(value = "id", defaultValue = "") String idString, @RequestParam(value = "nr", defaultValue = "") String nr) {
As ask, here are all RequestMappings from the controller (Sorry, I can't post the complete code from the controller here):
@Controller @RequestMapping("xyz/") public class Controller { @RequestMapping(value = "{language}/{country}/{term}/catalogue", method = RequestMethod.GET) @RequestMapping("**") @RequestMapping("{language}/{country}/product") @RequestMapping("{language}/{country}/product-detail") @RequestMapping("{language}/{country}/product-search") @RequestMapping("{language}/{country}/dealer-search") @RequestMapping("{language}/{country}/product-finder") @RequestMapping("{language}/{country}/table") @RequestMapping("**/languages") @RequestMapping("**/chooseLanguages") }
Thanks for help.
-
Erwin Bolwidt over 9 yearsCan you explain why this is a good idea, and what the relevant difference is with what the OP is already doing? Are you saying that "language" is somehow not a good name for a path variable?