Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguous mapping found with ControllerClassNameHandlerMapping

How to map requests to methods without explicit annotations on top of methods? For instance, the following request:

http://somedomain:8080/SampleSpring/access/loginFailed

should be mapped to

"loginFailed" method of "AccessController" without the need of explicit annotation on method like:

@RequestMapping("/access/loginFailed")

Here is my spring configuration:

<context:component-scan base-package="com.robikcodes.samplespring"/>
<mvc:annotation-driven/>

<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
        <property name="basePackage" value="com.robikcodes.samplespring.controller"/>
        <property name="caseSensitive" value="true"/>
        <property name="defaultHandler">
            <bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
        </property>
</bean>   

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/views/"/>
            <property name="suffix" value=".jsp"/>
</bean>

Here is my controller:

@Controller
public class AccessController{

    @RequestMapping(method = RequestMethod.GET)
    public void login(ModelMap m) {}

    @RequestMapping(method = RequestMethod.GET)
    public String loginFailed(ModelMap m) {
        m.addAttribute("error", "true");
        return "access/login";
    }

    @RequestMapping(method = RequestMethod.GET)
    public String logout(ModelMap m) {
        m.addAttribute("logoutStatus","true");
        return "access/login";
    }
}

I got the following error (seems like only login method was mapped properly):

org.apache.catalina.LifecycleException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'accessController' bean method 
public java.lang.String com.robikcodes.samplespring.controller.AccessController.logout(org.springframework.ui.ModelMap)
to {[],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'accessController' bean method
public void com.robikcodes.samplespring.controller.AccessController.login(org.springframework.ui.ModelMap) mapped.
like image 806
coolscitist Avatar asked Sep 16 '26 12:09

coolscitist


1 Answers

You're using ControllerClassNameHandlerMapping with an assumption that is not correct; from Java doc:

Implementation of HandlerMapping that follows a simple convention for generating URL path mappings from the class names of registered Controller beans as well as @Controller annotated beans.

The documentation does not say that it also follows method names. The main reference of comparing "handler mappings" for your controller is the @RequestMapping annotations put on your methods. So, with your controller Spring reads them as:

{methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}

for all the defined methods in AccessController that has the following @RequestMapping:

@RequestMapping(method = RequestMethod.GET)

That's why you see the ambiguous exception.

To my understanding, the cleanest solution is to use value attribute of @RequestMapping to define different request URIs. It's not really recommended to go for a solution that tries to map request URIs to method names.

like image 141
nobeh Avatar answered Sep 19 '26 16:09

nobeh