Announcement Announcement Module
Collapse
No announcement yet.
'Ambiguous mapping found' in controller with one POST mapping, why? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 'Ambiguous mapping found' in controller with one POST mapping, why?

    Hi guys.
    I'm using Spring 3.2.0.RELEASE, Security 3.1.3, MVC + WebFlow 2.3.1, Spring Social + Spring Social Security (both snapshoot), + Spring mongodb stuff.

    Spring Social + Spring Social Security initially have Spring 3.1.3 dependency, but I recompiled them with Spring 3.2.0.RELEASE locally and installed by gradle build script.

    I'm trying to create 'FB canvas' app and have one controller with ONE ONLY post method and I'm getting error above.

    Code:
    @Controller
    public class CanvasProviderSignInController {
    ...... // internal variables initialized by constructor....
    
        @RequestMapping(value = "/canvas", method = RequestMethod.POST)
        public String processFaceBookCanvasRequest(
                NativeWebRequest request) {
    ..........
    return NULL!!!;
    }
    
    
    Controller initialization:
    
    @Configuration
    public class SocialAndSecurityConfig {
        @Inject
        private Environment environment;
    ....... // different stuff
    
    
       	@Bean
       	public CanvasProviderSignInController providerSignInController() {
               CanvasProviderSignInController signInController = new CanvasProviderSignInController(
                       socialAuthenticationServiceLocator(),
                       facebookServiceProvider(),
                       usersConnectionRepository(),
                       signInAdapter(),
                       signedRequestDecoder()
               );
              return signInController;
       	}
    ..........
    I even removed all code from method returning NULL only, but I'm getting error:
    Code:
    20:51:39.015 [RMI TCP Connection(3)-127.0.0.1] ERROR o.s.web.context.ContextLoader - 
    Context initialization failed
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' 
    defined in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]: 
    Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping found. 
    Cannot map 'providerSignInController' bean method 
    public java.lang.String 
    com.web.controller.facebook.CanvasProviderSignInController.processFaceBookCanvasRequest(
    org.springframework.web.context.request.NativeWebRequest)
    to {[/canvas],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}:
     There is already 'canvasProviderSignInController' bean method
    public java.lang.String 
    com.web.controller.facebook.CanvasProviderSignInController.processFaceBookCanvasRequest(
    org.springframework.web.context.request.NativeWebRequest) mapped.
    .............
    Caused by: java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'providerSignInController' bean method 
    public java.lang.String 
    com.web.controller.facebook.CanvasProviderSignInController.processFaceBookCanvasRequest(
    org.springframework.web.context.request.NativeWebRequest)
    to {[/canvas],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}:
    There is already 'canvasProviderSignInController' bean method
    public java.lang.String 
    com.web.controller.facebook.CanvasProviderSignInController.processFaceBookCanvasRequest(
    org.springframework.web.context.request.NativeWebRequest) mapped
    Is there chance something is wrong with libraries? Here is the list.
    Code:
    activation-1.1.1.jar
    aopalliance-1.0.jar
    attoparser-1.1.jar
    commons-beanutils-1.8.0.jar
    commons-codec-1.6.jar
    commons-collections-3.2.1.jar
    commons-digester-2.0.jar
    commons-lang-2.4.jar
    commons-logging-1.1.1.jar
    guava-13.0.1.jar
    hibernate-validator-4.3.1.Final.jar
    httpclient-4.2.2.jar
    httpcore-4.2.2.jar
    jackson-core-asl-1.9.9.jar
    jackson-mapper-asl-1.9.9.jar
    javax.inject-1.jar
    jboss-logging-3.1.0.CR2.jar
    jcl-over-slf4j-1.7.1.jar
    joda-time-2.1.jar
    jstl-1.2.jar
    logback-classic-1.0.9.jar
    logback-core-1.0.9.jar
    lombok-0.11.6.jar
    mail-1.4.5.jar
    mongo-java-driver-2.10.1.jar
    sitemesh-3.0-alpha-2.jar
    slf4j-api-1.7.2.jar
    spring-aop-3.2.0.RELEASE.jar
    spring-beans-3.2.0.RELEASE.jar
    spring-binding-2.3.1.RELEASE.jar
    spring-context-3.2.0.RELEASE.jar
    spring-context-support-3.2.0.RELEASE.jar
    spring-core-3.2.0.RELEASE.jar
    spring-data-commons-core-1.4.0.RELEASE.jar
    spring-data-mongodb-1.1.0.RELEASE.jar
    spring-expression-3.2.0.RELEASE.jar
    spring-jdbc-3.2.0.RELEASE.jar
    spring-js-2.3.1.RELEASE.jar
    spring-js-resources-2.3.1.RELEASE.jar
    spring-security-acl-3.1.3.RELEASE.jar
    spring-security-config-3.1.3.RELEASE.jar
    spring-security-core-3.1.3.RELEASE.jar
    spring-security-taglibs-3.1.3.RELEASE.jar
    spring-security-web-3.1.3.RELEASE.jar
    spring-social-config-1.1.0.BUILD-SNAPSHOT.jar
    spring-social-core-1.1.0.BUILD-SNAPSHOT.jar
    spring-social-facebook-1.1.0.BUILD-SNAPSHOT.jar
    spring-social-facebook-web-1.1.0.BUILD-SNAPSHOT.jar
    spring-social-security-1.1.0.BUILD-SNAPSHOT.jar
    spring-social-web-1.1.0.BUILD-SNAPSHOT.jar
    spring-tx-3.2.0.RELEASE.jar
    spring-web-3.2.0.RELEASE.jar
    spring-webflow-2.3.1.RELEASE.jar
    spring-webmvc-3.2.0.RELEASE.jar
    thymeleaf-2.0.16-SNAPSHOT.jar
    thymeleaf-extras-conditionalcomments-2.0.0.jar
    thymeleaf-extras-springsecurity3-2.0.0.jar
    thymeleaf-extras-tiles2-2.0.0.jar
    thymeleaf-spring3-2.0.15.jar
    tiles-api-2.2.2.jar
    tiles-core-2.2.2.jar
    tiles-jsp-2.2.2.jar
    tiles-servlet-2.2.2.jar
    tiles-template-2.2.2.jar
    validation-api-1.0.0.GA.jar
    velocity-1.7.jar
    Last edited by blandger; Jan 23rd, 2013, 02:37 PM.

  • #2
    If I remove that controller, web-app starts fine.

    I also have following configuration stuff in related classes:
    Code:
    public class MainWebAppInitializer implements WebApplicationInitializer {
    ....// usual Dispatcher configuration with 'springSecurityFilterChain' configuration
    
    
    public class WebAppConfig extends WebMvcConfigurerAdapter {
    ......
        public void addViewControllers(ViewControllerRegistry registry) {
       		registry.addViewController("/canvas");
       	}
    ......
        @Bean
        public InternalResourceViewResolver viewResolver() {
            InternalResourceViewResolver resolver = new InternalResourceViewResolver();
            resolver.setViewClass(JstlView.class);
            resolver.setPrefix("/WEB-INF/views/");
            resolver.setSuffix(".jsp");
            resolver.setOrder(4);
            return resolver;
        }
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(localeChangeInterceptor());
    ......
        @Bean
        public LocaleChangeInterceptor localeChangeInterceptor() {
            LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
            localeChangeInterceptor.setParamName("lang"); // name of parameter for changing value
            return localeChangeInterceptor;
        }
    ........... // etc.

    Comment


    • #3
      I tried following:

      1. Create two methods only inside class:

      Code:
          @RequestMapping(value = "/canvas", method = RequestMethod.GET)
          public String processFaceBookCanvasRequest2(NativeWebRequest request) {
              return null;
          }
      
          @RequestMapping(value = "/canvas", method = RequestMethod.POST)
          public String processFaceBookCanvasRequest(NativeWebRequest request) {
              return null;
          }
      It fails.
      Code:
      Caused by: java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'providerSignInController' bean method 
      public java.lang.String com.web.controller.facebook.CanvasProviderSignInController.processFaceBookCanvasRequest2(org.springframework.web.context.request.NativeWebRequest)
      to {[/canvas],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'canvasProviderSignInController' bean method
      public java.lang.String com.web.controller.facebook.CanvasProviderSignInController.processFaceBookCanvasRequest2(org.springframework.web.context.request.NativeWebRequest) mapped.
      	at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.registerHandlerMethod(AbstractHandlerMethodMapping.java:179) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE]
      	at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.detectHandlerMethods(AbstractHandlerMethodMapping.java:145) ~[spring-webmvc-3.2.0.RELEASE.jar:3.2.0.RELEASE]

      2.
      Removing 'GET' method doesn't help. It fails on POST

      Code:
      Caused by: java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'providerSignInController' bean method 
      public java.lang.String com.web.controller.facebook.CanvasProviderSignInController.processFaceBookCanvasRequest(org.springframework.web.context.request.NativeWebRequest)
      to {[/canvas],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'canvasProviderSignInController' bean method
      public java.lang.String com.web.controller.facebook.CanvasProviderSignInController.processFaceBookCanvasRequest(org.springframework.web.context.request.NativeWebRequest) mapped.

      3.
      I removed all
      - dependencies inside class and left only EMPTY constructor, so it's contircted without params
      - removed all imports except
      import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.RequestMap ping;
      import org.springframework.web.bind.annotation.RequestMet hod;
      import org.springframework.web.context.request.NativeWebR equest;

      That didn't help, it fails with same anyway.

      Comment


      • #4
        OMG
        That should be included into FAQ.

        There are TWO OPTIONS:
        1. remove @Controller
        or
        2. remove @Bean
        annotation

        If I have Controller initialization in Config class:
        Code:
        @Configuration
        public class SocialAndSecurityConfig {
        .....
           	@Bean
           	public CanvasProviderSignInController providerSignInController() {
                  .......... // initialization stuff
                   CanvasProviderSignInController signInController = new CanvasProviderSignInController(...........);
                   return signInController;
           	}
        ........
        I should completely remove @Controller annotation from class:
        Code:
        //@Controller - REMOVE!
        public class CanvasProviderSignInController {
        ...............
        Otherwise the Controller (the @Bean at the same time) initialized TWICE and those error is thrown!
        First time controller is initialized explicitly, the second time by @ComponentScan(basePackages = {..... annotation in one of Java Config classes.

        I'm stupid dobby
        http://www.wearysloth.com/Gallery/Ac...6442-25820.gif

        Comment


        • #5
          If you remove the @Controller it isn't going to be detected properly anymore... Simply exclude this class form @ComponentScan (use an exludeFilter for it).

          Comment


          • #6
            Originally posted by Marten Deinum View Post
            If you remove the @Controller it isn't going to be detected properly anymore... Simply exclude this class form @ComponentScan (use an exludeFilter for it).
            I tried your way:
            Code:
            @Configuration
            @EnableWebMvc
            @ComponentScan(basePackages = {
                    "com.web.controller", // all controllers are there
                    "com.web.exception", // one global exception handler component
                    "com.web.formatter", // formatter component
                    "com.web.conversion" // conversion component
            }, excludeFilters = { @ComponentScan.Filter({
                    Configuration.class, CanvasProviderSignInController.class
            }) }
            )
            @Import({ServiceConfig.class, SocialAndSecurityConfig.class})
            @ImportResource("classpath:/webflow-config.xml")
            public class WebAppConfig extends WebMvcConfigurerAdapter {
            ..........
            }
            but that approach produces more weird error:
            13:52:38.172 [RMI TCP Connection(2)-127.0.0.1] ERROR o.s.web.context.ContextLoader - Context initialization failed
            java.lang.IllegalArgumentException: An error occured when processing a @ComponentScan ANNOTATION type filter: class com.web.controller.facebook.CanvasProviderSignInCo ntroller is not assignable to interface java.lang.annotation.Annotation
            at org.springframework.util.Assert.isAssignable(Asser t.java:368) ~[spring-core-3.2.0.RELEASE.jar:3.2.0.RELEASE]
            ...
            13:52:38.219 [RMI TCP Connection(2)-127.0.0.1] WARN o.s.w.c.s.AnnotationConfigWebApplicationContext - Exception thrown from LifecycleProcessor on context close
            java.lang.IllegalStateException: LifecycleProcessor not initialized - call 'refresh' before invoking lifecycle methods via the context: Root WebApplicationContext: startup date [Thu Jan 24 13:52:37 EET 2013]; root of context hierarchy
            at org.springframework.context.support.AbstractApplic ationContext.getLifecycleProcessor(AbstractApplica tionContext.java:360) [spring-context-3.2.0.RELEASE.jar:3.2.0.RELEASE]
            ......
            Probably because of dependencies to 'common-module' with business/DAO/service code. I think I'd better stick with removing @Controller annotation as it works.

            Comment


            • #7
              No because you have a wrong exclusion filter... Default is excludefilter based on Annotations, the CanvasProviderSignInController isn't an annotation. You need to specify a filter based on ASSIGNABLE_TYPE.

              Comment


              • #8
                Originally posted by Marten Deinum View Post
                No because you have a wrong exclusion filter... Default is excludefilter based on Annotations, the CanvasProviderSignInController isn't an annotation. You need to specify a filter based on ASSIGNABLE_TYPE.
                It would good to see correct exclusion.... for limiting 'round trips'.

                What am I doing wrong ?
                Code:
                @ComponentScan(basePackages = {
                        "com.web.controller", // all controllers are there
                ..........
                }, excludeFilters = { @ComponentScan.Filter({Configuration.class}),
                        @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = {CanvasProviderSignInController.class}) }
                )
                [2013-01-24 03:32:22,565] Artifact web-app: Artifact is being deployed, please wait...
                15:32:29.889 [RMI TCP Connection(3)-127.0.0.1] ERROR o.s.web.context.ContextLoader - Context initialization failed
                org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'canvasProviderSignInController' bean method
                public java.lang.String com.web.controller.facebook.CanvasProviderSignInCo ntroller.processFaceBookCanvasRequest(org.springfr amework.web.context.request.NativeWebRequest,org.s pringframework.ui.Model)
                to {[/canvas/],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'providerSignInController' bean method
                ..................

                Comment


                • #9
                  Why are you loading the controllers with the ContextLoaderLIstener? Those should be loaded by the dispatcherservlet, but anyway...

                  The exclusion should work if it doesn't make sure you don't have classloading issues as class identity is based on name and classloader, also make sure that if you have multiple @ComponentScan elements (on different @Configuration classes) they all scan and you need to exclude on all of them...

                  Comment


                  • #10
                    Originally posted by Marten Deinum View Post
                    Why are you loading the controllers with the ContextLoaderLIstener? Those should be loaded by the dispatcherservlet, but anyway...
                    Probably I don't know how to make that better way. I'm not sure, but looks like you are do that the same way in book. Don't you?
                    Code:
                    public class BookstoreWebApplicationInitializer implements WebApplicationInitializer { 
                    ....
                    private static final Class<?>[] configurationClasses = new Class<?>[] { TestDataContextConfiguration.class, ......
                    
                    	@Override
                    	public void onStartup(ServletContext servletContext) throws ServletException {
                    		registerListener(servletContext);
                    		registerDispatcherServlet(servletContext);  
                    .....
                    
                    private void registerListener(ServletContext servletContext) {
                    		AnnotationConfigWebApplicationContext rootContext = createContext(configurationClasses);
                    		servletContext.addListener(new ContextLoaderListener(rootContext));
                    		servletContext.addListener(new RequestContextListener());
                    	}
                    
                    private AnnotationConfigWebApplicationContext createContext(final Class<?>... annotatedClasses) {
                    		AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
                    		context.register(annotatedClasses);
                    		return context;
                    	}
                    ......
                    I'm using the similar approach and the same loading order.
                    The exclusion should work if it doesn't make sure you don't have classloading issues as class identity is based on name and classloader,
                    How is better to do that? By looking into code or in debugger? Anyway... it works that way...

                    also make sure that if you have multiple @ComponentScan elements (on different @Configuration classes) they all scan and you need to exclude on all of them...
                    I think it's not an issue, I checked twice and triple. I spent a lot of time yesterday on that. All DAO/service scanned in config classes basically inside 'common-module' and they don't have path for 'controllers' package.

                    Controllers are scanned at one place only:
                    Code:
                    @Configuration
                    @EnableWebMvc
                    @ComponentScan(basePackages = {
                            "com.web.controller", // all controllers are there
                    .............
                    }, excludeFilters = { @ComponentScan.Filter({Configuration.class}),
                            @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = {CanvasProviderSignInController.class}) }
                    )
                    @Import({ServiceConfig.class, SocialAndSecurityConfig.class})
                    @ImportResource("classpath:/webflow-config.xml")
                    public class WebAppConfig extends WebMvcConfigurerAdapter {
                    ............

                    Comment


                    • #11
                      Originally posted by blandger View Post
                      .......I think it's not an issue, I checked twice and triple. I spent a lot of time yesterday on that. All DAO/service scanned in config classes basically inside 'common-module' and they don't have path for 'controllers' package.
                      Controllers are scanned at one place only:.........
                      Marten, I'm taking my words back and bring my apologize... Indeed, there was one more 'component scan'. It was inside:
                      Code:
                      webflow-config.xml
                          <context:component-scan base-package="com.web"/>
                      Error gone when I've change it to:
                      Code:
                          <context:component-scan base-package="com.web">
                              <context:include-filter type="regex" expression="com.web.*initialize.*"/>
                              <context:exclude-filter type="assignable"
                                                      expression="com.web.controller.facebook.CanvasProviderSignInController"/>
                          </context:component-scan>
                      That stopped failing with stupid error and @Controller in back to controller class declaration.

                      Comment

                      Working...
                      X