I'm getting the following exception if I use multi level urls in class like @RequestMapping("/api/v0.1")
:
java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'userController'
bean method getUsers()|to {[/api/v0.1]}: There is already 'userController' bean
method getUser(java.lang.String) mapped.
It's like the method level mappings doesn't get into consideration at all.
But it's ok if I put @RequestMapping("/api")
i.e. remove the /v0.1
part.
Here is the configuration stripped up to the minimal case:
@Controller
@RequestMapping("/api/v0.1")
public class UserController {
@RequestMapping(value = "/users")
@ResponseBody
public List<User> getUsers() {
return null;
}
@RequestMapping(value = "/users/{username}")
@ResponseBody
public User getUser(@PathVariable String username) {
return null;
}
}
web.xml
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
servlet-context.xml:
<!-- Configures the @Controller programming model -->
<mvc:annotation-driven />
<!-- Forwards requests to the "/" resource to the "welcome" view -->
<mvc:view-controller path="/" view-name="home"/>
<!-- Handles HTTP GET requests for /assets/** by efficiently serving up static resources in the ${webappRoot}/resources/ directory -->
<mvc:resources mapping="/assets/**" location="/assets/" />
I'm using spring 3.1. I also tried to set alwaysUseFullPath
property to true of the RequestMappingHandlerMapping
bean but it didn't change the situation.
Very interesting issue - I checked what could be going on, you are right the "v0.1" is really throwing off the org.springframework.util.AntPathMatcher
which creates the full URI path by combining the path from the controller and the path from the mapped method. If it sees a "file.extension" kind of a pattern in the Controller, then it totally ignores the path mapping of the method - this is the reason why your @PathVariable
was getting ignored.
I am not sure if this is a bug or intended behavior in Spring MVC, temporary fix would be along what you have already mentioned -
1.To remove "v0.1" from the RequestMapping of Controller and make it without extension say v0_1
2.To put this mapping in the mapped method:
@Controller
@RequestMapping("/api")
public class UserController {
@RequestMapping(value = "/v0.1/users")
@ResponseBody
public List<User> getUsers() {
return null;
}
@RequestMapping(value = "/v0.1/users/{username}")
@ResponseBody
public User getUser(@PathVariable String username) {
return null;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With