Ambiguous mapping. Cannot map ‘basicErrorController’ method

Spring boot error Ambiguous mapping. Cannot map ‘basicErrorController’ method occurs when the url ‘/error’ url is configured in the request mapping annotation of the rest controller method. By default, “/error” is mapped in the BasicErrorController class to handle errors and exceptions in the spring boot application. This error occurs when the url is mapped again to the custom controller class.

The Whitelabel Error Page error page is shown in “/error” in the spring boot application. You see this exception because you are trying to overwrite the “/error” url using a custom rest controller. The rest controller will not allow two methods to be configured with the same url.

The spring boot application throws BeanCreationException Error creating bean with the name ‘requestMappingHandlerMapping’ defined in the class path resource as the requestMappingHandlerMapping bean fails with this exception.



Exception

The exception stack trace will be shown below. This will be displayed in the console when the application starts.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'basicErrorController' method 
 org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)
 to { /error}: There is already 'myErrorController' bean method
 com.test.MyErrorController#myerror() mapped.
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1803) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
     at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
     at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
     at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
     at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
     at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.2.1.RELEASE.jar:2.2.1.RELEASE]
     at com.test.SpringHelloWorldJspApplication.main(SpringHelloWorldJspApplication.java:10) [classes/:na]
 Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'basicErrorController' method 
 org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)
 to { /error}: There is already 'myErrorController' bean method
 com.test.MyErrorController#myerror() mapped.
     at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.validateMethodMapping(AbstractHandlerMethodMapping.java:633) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.register(AbstractHandlerMethodMapping.java:600) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.registerHandlerMethod(AbstractHandlerMethodMapping.java:318) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.registerHandlerMethod(RequestMappingHandlerMapping.java:350) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.registerHandlerMethod(RequestMappingHandlerMapping.java:67) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lambda$detectHandlerMethods$1(AbstractHandlerMethodMapping.java:288) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) ~[na:1.8.0_101]
     at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.detectHandlerMethods(AbstractHandlerMethodMapping.java:286) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.processCandidateBean(AbstractHandlerMethodMapping.java:258) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initHandlerMethods(AbstractHandlerMethodMapping.java:217) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.afterPropertiesSet(AbstractHandlerMethodMapping.java:205) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.afterPropertiesSet(RequestMappingHandlerMapping.java:171) ~[spring-webmvc-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1862) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1799) ~[spring-beans-5.2.1.RELEASE.jar:5.2.1.RELEASE]
     … 16 common frames omitted


How to reproduce this exception

The url “/error” is already configured in BasicErrorController class in spring boot framework. If a custom rest controller class is created with the url mapping request as “/error”, the spring boot framework will throw “Ambiguous mapping. Cannot map ‘basicErrorController’ method” exception.

package com.yawintutor;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyErrorController  {

	@RequestMapping(value = "/error")
	public String myerror() {
		return "<center><h1>Something went wrong</h1></center>";
	}
}


Root Cause

The Spring boot application uses the default error page for any error that has occurred. It uses the “BasicErrorController” to map the “/error” url page. If any custom rest controller class uses the “/error” url without implementing the ErrorController interface, this error is thrown from the spring boot framework.

The “/error” url can not be used in any custom rest controller class unless it is implemented using the ErrorController interface.



Solution 1

The “/error” url is already configured in the spring boot framework to handle exceptions and errors. If you do not intend to customize your default error page, change the “/error” url to something else in the custom rest controller class that you have created. If you have created the “/error” url by mistake, change it to another name. This will resolve the exception “Ambiguous mapping. Cannot map ‘basicErrorController’ method”.

package com.yawintutor;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyErrorController  {

	@RequestMapping(value = "/myerror")
	public String myerror() {
		return "<center><h1>Something went wrong</h1></center>";
	}
}


Solution 2

Spring boot uses the “/error” url of the “BasicErrorController” class to display the default “Whitelabel Error Page” error page when an error or exception occurs in the application. The default BasicErrorController class implementation of the “/error” url can be customized using the ErrorController interface.

To customized the default error page, create a custom rest controller class by implementing the ErrorController interface. Create a method with url as “/error” in RequestMapping annotation. The below example shows a sample implementation of the default error page.

package com.yawintutor;

import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyErrorController implements ErrorController {

	private static final String PATH = "/error";

	@RequestMapping(value = PATH )
	public String myerror() {
		return "<center><h1>Something went wrong</h1></center>";
	}

	@Override
	public String getErrorPath() {
		return PATH;
	}
}



Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *