Spring MVC 3 : Ambiguous mapping found

48,486

Solution 1

If you have a controller as given below, all requests other than /book/edit will be directed to mydefault() while /book/edit will be sent to meet().

@Controller
@RequestMapping("/book")
public class BookController {

    @RequestMapping
    public @ResponseBody String mydefault() {
        return "Hi Book!";
    }

    @RequestMapping("/edit")
    public @ResponseBody String meet() {
        return "Nice to meet you Book!";
    }
}

In your sample you have two methods without explicit path mapping.

Solution 2

Arun, your answer is correct with the caveat that in Spring 3.1 it depends which HandlerMapping-HandlerAdapter pair is configured.

The described behavior is supported with the DefaultAnnotationHandlerMapping & AnnotationMethodHandlerAdapter which have been in use since Spring 2.5 and are still enabled by default when no other HandlerMapping and HandlerAdapter beans are defined.

The RequestMappingHandlerMapping and RequestMappingHandlerAdapter added in Spring 3.1 (see Spring 3.1 reference docs) as a replacement for the former do not support the same behavior -- i.e. falling back on the method name in case of ambiguous mappings as well as having a default method (when no explicit mappings are defined). The new HandlerMapping-HandlerAdapter pair is enabled by default from the MVC namespace and from MVC Java config and is recommended for use going forward.

The Java doc referenced by Arun needs an update. I've created a ticket for that SPR-9042.

Share:
48,486
Amit Patel
Author by

Amit Patel

A freelance developer based in Ahmedabad, India. Passionate about web technologies and following best practices. Focusing on Ruby on Rails. I still love vanilla JS and jQuery. LinkedIn: https://www.linkedin.com/in/amitsavani Email: amit [DOT] savani [AT] gmail

Updated on October 25, 2020

Comments

  • Amit Patel
    Amit Patel over 3 years

    I am playing with spring MVC 3.1 and testing different features. I wanted to verify following statement taken from @RequestMapping#value doc

    If you have a single default method (without explicit path mapping), then all requests without a more specific mapped method found will be dispatched to it. If you have multiple such default methods, then the method name will be taken into account for choosing between them
    

    So I created following controller with multiple default handler methods.

    @Controller
    @RequestMapping("/book")
    public class BookController {
    
        @RequestMapping
        public @ResponseBody String greet() {
            return "Hi Book!";
        }
    
        @RequestMapping
        public @ResponseBody String meet() {
            return "Nice to meet you Book!";
        }
    }
    

    Here is web application context configuration

    <beans ....>
    <!-- Use @Component annotations for bean definitions -->
      <context:component-scan base-package="com.botreeconsulting.lms.web"/>
    
      <!-- Use @Controller annotations for MVC controller definitions -->
      <mvc:annotation-driven />
    
      <bean id="viewResolver"
            class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    
            <property name="prefix">
                <value>/WEB-INF/views/</value>
            </property>
            <property name="suffix">
                <value>.jsp</value>
            </property>
       </bean>
    
    </beans>
    

    But it seems I messed up something as it is giving me following error at the time of deployment:

    java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'bookController' bean method 
    public java.lang.String com.botreeconsulting.lms.web.BookController.meet()
    to {[/book],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'bookController' bean method
    public java.lang.String com.botreeconsulting.lms.web.BookController.greet() mapped.
    

    Now the question is does this controller models what is written in the document? I feel that I didn't get it properly. Please guide me to model the controller to match the statement about multiple default handlers.

    Thanks, Amit

  • Amit Patel
    Amit Patel over 12 years
    mydefault() will handle /book only not /book/abc.
  • Amit Patel
    Amit Patel over 12 years
    Arun, If you have multiple such default methods.... Is it possible to configure multiple default methods?
  • Arun P Johny
    Arun P Johny over 12 years
    What do you mean by multiple defaults? In any design there will be only one default
  • Amit Patel
    Amit Patel over 12 years
    Arun, I understand that there is only single default possible in a controler. Now how come this Spring document comment says If you have a single default method (without explicit path mapping), then all requests without a more specific mapped method found will be dispatched to it. If you have multiple such default methods, then the method name will be taken into account for choosing between them?
  • Arun P Johny
    Arun P Johny over 12 years
    I think what it means is if you have more than 1 method without the url mapping(ie with only @RequestMappin no path speficied` then the name of the method will be considered. Assume that to the above example you add a method named add with annotation @RequestMapping and then you request /book/add then the add method will be called.
  • Amit Patel
    Amit Patel over 12 years
    Exactly, that's what I wanted to check ahd hence I created the example with multiple methods with @ReqeustMapping(without explicit path) and ended with ambiguity error. All I wanted is to validate that it is not possible to have multiple default request mapping methods even though it is stated in the document.
  • Arun P Johny
    Arun P Johny over 12 years
    Can you share your spring mvc configuration? Are you using an RequestMappingHandlerMapping or DefaultAnnotationHandlerMapping
  • Arun P Johny
    Arun P Johny over 12 years
    You can have a look at the answer provided by Rossen Stoyanchev also.
  • Amit Patel
    Amit Patel over 12 years
    I haven't specified HandlerMapping explicitly so it would be DefaultAnnotationHandlerMapping as Rossen Stoyanchev posted. For reference I have added mvc configuration in original post
  • Boris Treukhov
    Boris Treukhov over 11 years
    Hi, Rossen. Can you please clarify a bit the statement enabled by default from the MVC namespace - do you mean <mvc:annotation-config> tag, or the tag registers just another pair of HandlerMapping/HandlerAdapter?
  • Boris Treukhov
    Boris Treukhov over 11 years
    Also, can you please look at stackoverflow.com/questions/13671776/… - in this question the controller is annotated only with '@Controller' while its single method is annotated '@RequestMapping("/hello")' am I understanding correctly that this configuration will work only in pre 3.1 versions(without <mvc:annotation-driven> tag) because of the changes in Spring 3.1?