196

I'm trying to remove white label error page, so what I've done was created a controller mapping for "/error",

@RestController
public class IndexController {

    @RequestMapping(value = "/error")
    public String error() {
        return "Error handling";
    }

}

But now I"m getting this error.

Exception in thread "AWT-EventQueue-0" 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 'basicErrorController' bean method 
public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>>  org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletR equest)
to {[/error],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'indexController' bean method

Don't know whether I'm doing anything wrong. Please advice.

EDIT:

Already added error.whitelabel.enabled=false to application.properties file, still getting the same error

4
  • 1
    Look at this project github.com/paulc4/mvc-exceptions/blob/master/src/main/java/…, seems they have error page remapping in it. Commented Aug 18, 2014 at 6:01
  • Have you tried setting spring.resources.add-mappings=false? Commented Aug 18, 2014 at 7:31
  • Thanks for the suggestion, Yes still got the same error Commented Aug 18, 2014 at 8:07
  • Are you just trying to return some custom content when the /error path is called? Commented Aug 18, 2014 at 11:31

19 Answers 19

275

You need to change your code to the following:

@RestController
public class IndexController implements ErrorController{

    private static final String PATH = "/error";

    @RequestMapping(value = PATH)
    public String error() {
        return "Error handling";
    }

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

Your code did not work, because Spring Boot automatically registers the BasicErrorController as a Spring Bean when you have not specified an implementation of ErrorController.

To see that fact just navigate to ErrorMvcAutoConfiguration.basicErrorController here.

Sign up to request clarification or add additional context in comments.

12 Comments

Ran into the same into the same issue, I searched the Spring docs but it didn't mention BasicErrorController. This works :)
I had to go through the source to find this one :-)
Thanks, worked nicely! A small follow-up if you can give any pointers: say we get in this error handler because some exception was thrown in our app (and Spring implicitly sets response code to 500 which is correct); is there an easy way to get hold of that exception here (to include some details in error message returned)?
Glad you found it useful! Although I haven't tried it, I am pretty sure that you can use the principles found in Spring Boot's BasicErrorController (see github.com/spring-projects/spring-boot/blob/…) to accomplish what you want
Hmm, yes, thanks again! At first I wasn't sure how to get that ErrorAttributes object (containing the error details), but then I tried simply @Autowiring it, and it works. What I went with for now: gist.github.com/jonikarppinen/662c38fb57a23de61c8b
|
61

Spring boot doc 'was' wrong (they have since fixed it) :

To switch it off you can set error.whitelabel.enabled=false

should be

To switch it off you can set server.error.whitelabel.enabled=false

1 Comment

This will disable the White Label Error Page but spring boot will map the endpoint /error anyway. To free the endpoint /error set server.error.path=/error-spring or some alternative path.
46

If you want a more "JSONish" response page you can try something like that:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ErrorAttributes;
import org.springframework.boot.autoconfigure.web.ErrorController;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@RestController
@RequestMapping("/error")
public class SimpleErrorController implements ErrorController {

  private final ErrorAttributes errorAttributes;

  @Autowired
  public SimpleErrorController(ErrorAttributes errorAttributes) {
    Assert.notNull(errorAttributes, "ErrorAttributes must not be null");
    this.errorAttributes = errorAttributes;
  }

  @Override
  public String getErrorPath() {
    return "/error";
  }

  @RequestMapping
  public Map<String, Object> error(HttpServletRequest aRequest){
     Map<String, Object> body = getErrorAttributes(aRequest,getTraceParameter(aRequest));
     String trace = (String) body.get("trace");
     if(trace != null){
       String[] lines = trace.split("\n\t");
       body.put("trace", lines);
     }
     return body;
  }

  private boolean getTraceParameter(HttpServletRequest request) {
    String parameter = request.getParameter("trace");
    if (parameter == null) {
        return false;
    }
    return !"false".equals(parameter.toLowerCase());
  }

  private Map<String, Object> getErrorAttributes(HttpServletRequest aRequest, boolean includeStackTrace) {
    RequestAttributes requestAttributes = new ServletRequestAttributes(aRequest);
    return errorAttributes.getErrorAttributes(requestAttributes, includeStackTrace);
  }
}

3 Comments

In Spring-Boot v2 the ErrorController and ErrorAttributes classes are in package org.springframework.boot.web.servlet.error and further the ErrorAttributes#getErrorAttributes method signature has changed, please note dependency on Spring-Boot v1 and possibly give hints for v2, thx.
Change : private Map<String, Object> getErrorAttributes(HttpServletRequest aRequest, boolean includeStackTrace) { RequestAttributes requestAttributes = new ServletRequestAttributes(aRequest); return errorAttributes.getErrorAttributes(requestAttributes, includeStackTrace); } By : private Map<String, Object> getErrorAttributes(HttpServletRequest request, boolean includeStackTrace) { WebRequest webRequest = new ServletWebRequest(request); return this.errorAttributes.getErrorAttributes(webRequest, includeStackTrace); }
An updated version of SimpleErrorController.java considering the comments from above can be found in here > gist.github.com/oscarnevarezleal/…
36

You can remove it completely by specifying:

import org.springframework.context.annotation.Configuration;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
...
@Configuration
@EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class})
public static MainApp { ... }

However, do note that doing so will probably cause servlet container's whitelabel pages to show up instead :)


EDIT: Another way to do this is via application.yaml. Just put in the value:

spring:
  autoconfigure:
    exclude: org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration

Documentation

For Spring Boot < 2.0, the class is located in package org.springframework.boot.autoconfigure.web.

Comments

19

Manual here says that you have to set server.error.whitelabel.enabled to false to disable the standard error page. Maybe it is what you want?

I am experiencing the same error after adding /error mapping, by the way.

2 Comments

Yes I've already set error.whitelabel.enabled=false but still getting the same error after adding /error mapping
This will disable the White Label Error Page but spring boot will map the endpoint /error anyway. To free the endpoint /error set server.error.path=/error-spring or some alternative path.
14

This depends on your spring boot version:

When SpringBootVersion <= 1.2 then use error.whitelabel.enabled = false

When SpringBootVersion >= 1.3 then use server.error.whitelabel.enabled = false

Comments

13

With Spring Boot > 1.4.x you could do this:

@SpringBootApplication(exclude = {ErrorMvcAutoConfiguration.class})
public class MyApi {
  public static void main(String[] args) {
    SpringApplication.run(App.class, args);
  }
}

but then in case of exception the servlet container will display its own error page.

Comments

7

In Spring Boot 1.4.1 using Mustache templates, placing error.html under templates folder will be enough:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>Error</title>
</head>

<body>
  <h1>Error {{ status }}</h1>
  <p>{{ error }}</p>
  <p>{{ message }}</p>
  <p>{{ path }}</p>
</body>

</html>

Additional variables can be passed by creating an interceptor for /error

1 Comment

5

I am using Spring Boot version 2.1.2 and the errorAttributes.getErrorAttributes() signature didn't work for me (in acohen's response). I wanted a JSON type response so I did a little digging and found this method did exactly what I needed.

I got most of my information from this thread as well as this blog post.

First, I created a CustomErrorController that Spring will look for to map any errors to.

package com.example.error;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.WebRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@RestController
public class CustomErrorController implements ErrorController {

    private static final String PATH = "error";

    @Value("${debug}")
    private boolean debug;

    @Autowired
    private ErrorAttributes errorAttributes;

    @RequestMapping(PATH)
    @ResponseBody
    public CustomHttpErrorResponse error(WebRequest request, HttpServletResponse response) {
        return new CustomHttpErrorResponse(response.getStatus(), getErrorAttributes(request));
    }

    public void setErrorAttributes(ErrorAttributes errorAttributes) {
        this.errorAttributes = errorAttributes;
    }

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

    private Map<String, Object> getErrorAttributes(WebRequest request) {
        Map<String, Object> map = new HashMap<>();
        map.putAll(this.errorAttributes.getErrorAttributes(request, this.debug));
        return map;
    }
}

Second, I created a CustomHttpErrorResponse class to return the error as JSON.

package com.example.error;

import java.util.Map;

public class CustomHttpErrorResponse {

    private Integer status;
    private String path;
    private String errorMessage;
    private String timeStamp;
    private String trace;

    public CustomHttpErrorResponse(int status, Map<String, Object> errorAttributes) {
        this.setStatus(status);
        this.setPath((String) errorAttributes.get("path"));
        this.setErrorMessage((String) errorAttributes.get("message"));
        this.setTimeStamp(errorAttributes.get("timestamp").toString());
        this.setTrace((String) errorAttributes.get("trace"));
    }

    // getters and setters
}

Finally, I had to turn off the Whitelabel in the application.properties file.

server.error.whitelabel.enabled=false

This should even work for xml requests/responses. But I haven't tested that. It did exactly what I was looking for since I was creating a RESTful API and only wanted to return JSON.

Comments

3

Here's an alternative method which is very similar to the "old way" of specifying error mappings in web.xml.

Just add this to your Spring Boot configuration:

@SpringBootApplication
public class Application implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {

    @Override
    public void customize(ConfigurableServletWebServerFactory factory) {
        factory.addErrorPages(new ErrorPage(HttpStatus.FORBIDDEN, "/errors/403.html"));
        factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/errors/404.html"));
        factory.addErrorPages(new ErrorPage("/errors/500.html"));
    }

}

Then you can define the error pages in the static content normally.

The customizer can also be a separate @Component, if desired.

Comments

3

Spring Boot by default has a “whitelabel” error page which you can see in a browser if you encounter a server error. Whitelabel Error Page is a generic Spring Boot error page which is displayed when no custom error page is found.

Set “server.error.whitelabel.enabled=false” to switch of the default error page

Comments

3

I had a similar issue WhiteLabel Error message on my Angular SPA whenever I did a refresh.

The fix was to create a controller that implements ErrorController but instead of returning a String, I had to return a ModelAndView object that forwards to /

@CrossOrigin
@RestController
public class IndexController implements ErrorController {
    
    private static final String PATH = "/error";
    
    @RequestMapping(value = PATH)
    public ModelAndView saveLeadQuery() {           
        return new ModelAndView("forward:/");
    }

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

Comments

2

server.error.whitelabel.enabled=false

Include the above line to the Resources folders application.properties

More Error Issue resolve please refer http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-customize-the-whitelabel-error-page

1 Comment

I tried application.properties in my installation folder which did nothing. The application.properties folder under /src/main/resources is what suganya sudarsan was attempting to convey. It appears to be a "hot read" in Eclipse as well.
2

I was trying to call a REST endpoint from a microservice and I was using the resttemplate's put method.

In my design if any error occurred inside the REST endpoint it should return a JSON error response, it was working for some calls but not for this put one, it returned the white label error page instead.

So I did some investigation and I found out that;

Spring try to understand the caller if it is a machine then it returns JSON response or if it is a browser than it returns the white label error page HTML.

As a result: my client app needed to say to REST endpoint that the caller is a machine, not a browser so for this the client app needed to add 'application/json' into the ACCEPT header explicitly for the resttemplate's 'put' method. I added this to the header and solved the problem.

my call to the endpoint:

restTemplate.put(url, request, param1, param2);

for above call I had to add below header param.

headers.set("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);

or I tried to change put to exchange as well, in this case, exchange call added the same header for me and solved the problem too but I don't know why :)

restTemplate.exchange(....)

Comments

1

Solution posted by geoand works for me. In addition to this, if you want to redirect to any specific page then you may use this.

@RequestMapping(value = PATH)
public void error(HttpServletResponse response) {
    response.sendRedirect("/");   //provide your error page url or home url
}

Full Code snippet below:

@RestController
public class IndexController implements ErrorController{

    private static final String PATH = "/error";

    @RequestMapping(value = PATH)
    public void error(HttpServletResponse response) {
         response.sendRedirect("/");   //provide your error page url or home url
    }

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

PS: Since, unable to edit above answer, hence posting this as new answer.

Comments

1

Custom error page in JSON format for Spring Boot > 2.3.0

package com.example.api.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.WebRequest;

import javax.servlet.http.HttpServletResponse;
import java.util.Map;

@RestController
public class CustomErrorController implements ErrorController {
    private static final String PATH = "/error";

    @Autowired
    private ErrorAttributes errorAttributes;

    @RequestMapping(PATH)
    public Map<String, Object> error(WebRequest request, HttpServletResponse response) {
        return getErrorAttributes(request, true);
    }

    private Map<String, Object> getErrorAttributes(WebRequest request, boolean includeStackTrace) {
        ErrorAttributeOptions options = ErrorAttributeOptions.defaults()
                .including(ErrorAttributeOptions.Include.MESSAGE)
                .including(ErrorAttributeOptions.Include.EXCEPTION)
                .including(ErrorAttributeOptions.Include.BINDING_ERRORS);
        if(includeStackTrace){
            options = options.including(ErrorAttributeOptions.Include.STACK_TRACE);
        }
        return this.errorAttributes.getErrorAttributes(request, options);
    }
}

Comments

0

Best option would be to create a HTML page (JSP,THYMELEAF) with the name "error.html", it would redirect every whitelable error to this page . You can customize it after .

Comments

0

We can easily handle white label error in Java Spring boot. Just add this class in configuration file..

import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebRoutingConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/urlNotFound")
                // the viewName should be specified, in our case we forward to the index.html 
                .setViewName("forward:/index.html");
    }

    @Bean
    public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> containerCustomizer() {
        return container -> {
            container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND,
                    "/urlNotFound"));
        };
    }

}

Comments

0

I literally missed to add the @RestController annotation in my code somehow. Silly as it may sound, but worth keeping written down somewhere if you ask me, just in-case if you miss that one in a rush..

@RestController
public class MyApiController implements MyApi {
.
.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.