5

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.

2 Answers 2

2

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;
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

I remember trying @RequestMapping("/api/v01") on class level (without the dot) and not getting a result but I'll try again and let you know. thanks.
Since the AntPathMatcher allows regular expressions, I think if you escaped the dot it would work. eg. v0\.1
0

You should use the @RequestMapping(value = "/{version:.*}/users") to include the dot '.' in the path variable

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.