[spring] Spring Boot Remove Whitelabel Error Page

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

This question is related to spring spring-boot

The answer is


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;
    }
}

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.


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.


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.


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


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);
  }
}

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


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(....)

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


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


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.


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


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.


Examples related to spring

Are all Spring Framework Java Configuration injection examples buggy? Two Page Login with Spring Security 3.2.x Access blocked by CORS policy: Response to preflight request doesn't pass access control check Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean Failed to auto-configure a DataSource: 'spring.datasource.url' is not specified Spring Data JPA findOne() change to Optional how to use this? After Spring Boot 2.0 migration: jdbcUrl is required with driverClassName The type WebMvcConfigurerAdapter is deprecated No converter found capable of converting from type to type

Examples related to spring-boot

Access blocked by CORS policy: Response to preflight request doesn't pass access control check Why am I getting Unknown error in line 1 of pom.xml? Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured How to resolve Unable to load authentication plugin 'caching_sha2_password' issue ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean Failed to auto-configure a DataSource: 'spring.datasource.url' is not specified After Spring Boot 2.0 migration: jdbcUrl is required with driverClassName ERROR Source option 1.5 is no longer supported. Use 1.6 or later How to start up spring-boot application via command line? JSON parse error: Can not construct instance of java.time.LocalDate: no String-argument constructor/factory method to deserialize from String value