Spring Boot Eliminar página de error Whitelabel

156

Estoy tratando de eliminar la página de error de etiqueta blanca, así que lo que hice fue crear una asignación de controlador para "/ error",

@RestController
public class IndexController {

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

}

Pero ahora recibo este 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

No sé si estoy haciendo algo mal. Por favor aconséjame.

EDITAR:

Ya se ha agregado error.whitelabel.enabled=false al archivo application.properties, pero sigue obteniendo el mismo error

Yasitha Waduge
fuente
1
Mire este proyecto github.com/paulc4/mvc-exceptions/blob/master/src/main/java/… , parece que tienen una reasignación de página de error.
Innot Kauker
¿Has intentado configurar spring.resources.add-mappings=false?
geoand
Gracias por la sugerencia, Sí todavía recibí el mismo error
Yasitha Waduge
¿Estás intentando devolver algún contenido personalizado cuando /errorse llama a la ruta?
geoand

Respuestas:

240

Necesita cambiar su código a lo siguiente:

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

Su código no funcionó, porque Spring Boot lo registra automáticamente BasicErrorControllercomo Spring Bean cuando no ha especificado una implementación de ErrorController.

Para ver ese hecho solo navega hasta ErrorMvcAutoConfiguration.basicErrorController aquí .

geoand
fuente
1
Me encontré con el mismo problema, busqué en los documentos de Spring pero no mencionó BasicErrorController. Esto funciona :)
Mike R
44
Tuve que revisar la fuente para encontrar este :-)
geoand
1
Gracias, funcionó muy bien! Un pequeño seguimiento si puede dar algunos indicadores: digamos que entramos en este controlador de errores porque se produjo alguna excepción en nuestra aplicación (y Spring establece implícitamente el código de respuesta en 500, que es correcto); ¿Hay alguna manera fácil de obtener esa excepción aquí (para incluir algunos detalles en el mensaje de error devuelto)?
Jonik
1
¡Me alegra que lo hayas encontrado útil! Aunque no lo he probado, estoy bastante seguro de que puede usar los principios que se encuentran en Spring Boot's BasicErrorController(consulte github.com/spring-projects/spring-boot/blob/… ) para lograr lo que desea
geoand
3
Hmm, sí, ¡gracias de nuevo! Al principio no estaba seguro de cómo obtener ese ErrorAttributesobjeto (que contiene los detalles del error), pero luego intenté simplemente @Autowiring y funciona. Lo que elegí
Jonik
44

Si desea una página de respuesta más "JSONish", puede intentar algo como eso:

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);
  }
}
acohen
fuente
77
En Spring-Boot v2, las clases ErrorController y ErrorAttributes están en el paquete org.springframework.boot.web.servlet.error y además la firma del método ErrorAttributes # getErrorAttributes ha cambiado, tenga en cuenta la dependencia de Spring-Boot v1 y posiblemente dé pistas para v2, Gracias.
chrisinmtown
1
Cambio: mapa privado <String, Object> getErrorAttributes (HttpServletRequest aRequest, boolean includeStackTrace) {RequestAttributes requestAttributes = new ServletRequestAttributes (aRequest); return errorAttributes.getErrorAttributes (requestAttributes, includeStackTrace); } Por: mapa privado <String, Object> getErrorAttributes (solicitud HttpServletRequest, boolean includeStackTrace) {WebRequest webRequest = new ServletWebRequest (request); devuelve this.errorAttributes.getErrorAttributes (webRequest, includeStackTrace); }
Rija Ramampiandra
2
Una versión actualizada de SimpleErrorController.java considerando los comentarios de arriba se puede encontrar aquí> gist.github.com/oscarnevarezleal/…
Oscar Nevarez
38

Spring boot doc 'estaba' mal (lo han arreglado desde entonces):

Para desactivarlo, puede establecer error.whitelabel.enabled = false

debiera ser

Para desactivarlo, puede configurar server.error.whitelabel.enabled = false

willome
fuente
Esto deshabilitará la página de error de etiqueta blanca, pero el inicio de primavera asignará el punto final de /errortodos modos. Para liberar el /errorconjunto de puntos finales server.error.path=/error-springo alguna ruta alternativa.
notes-jj
32

Puede eliminarlo completamente especificando:

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

Sin embargo, tenga en cuenta que hacerlo probablemente hará que aparezcan las páginas de etiqueta blanca del contenedor de servlet :)


EDITAR: Otra forma de hacerlo es a través de application.yaml. Solo pon el valor:

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

Documentación

Para Spring Boot <2.0, la clase se encuentra en el paquete org.springframework.boot.autoconfigure.web.

sudadera con capucha
fuente
15

Manual de aquí dice que usted tiene que fijar server.error.whitelabel.enableda falsedesactivar la página de error estándar. Tal vez es lo que quieres?

Por cierto, estoy experimentando el mismo error después de agregar / mapeo de errores.

Innot Kauker
fuente
Sí, ya configuré error.whitelabel.enabled = false pero sigo recibiendo el mismo error después de agregar / mapeo de errores
Yasitha Waduge
Esto deshabilitará la página de error de etiqueta blanca, pero el inicio de primavera asignará el punto final de /errortodos modos. Para liberar el /errorconjunto de puntos finales server.error.path=/error-springo alguna ruta alternativa.
notes-jj
11

Con Spring Boot> 1.4.x puedes hacer esto:

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

pero luego, en caso de excepción, el contenedor de servlet mostrará su propia página de error.

db80
fuente
8

Esto depende de su versión de arranque de primavera:

Cuando SpringBootVersion <= 1.2entonces useerror.whitelabel.enabled = false

Cuando SpringBootVersion > = 1.3entonces useserver.error.whitelabel.enabled = false

sendon1982
fuente
6

En Spring Boot 1.4.1 con plantillas de bigote, basta con colocar error.html en la carpeta de plantillas:

<!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>

Se pueden pasar variables adicionales creando un interceptor para /error

Ecmel Ercan
fuente
3

Aquí hay un método alternativo que es muy similar a la "forma antigua" de especificar asignaciones de error en web.xml.

Simplemente agregue esto a su configuración de Spring Boot:

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

}

Luego puede definir las páginas de error en el contenido estático normalmente.

El personalizador también puede ser independiente @Component, si lo desea.

rustyx
fuente
3

Estoy usando Spring Boot versión 2.1.2 y la errorAttributes.getErrorAttributes()firma no funcionó para mí (en respuesta de acohen). Quería una respuesta tipo JSON, así que investigué un poco y descubrí que este método hacía exactamente lo que necesitaba.

Obtuve la mayor parte de mi información de este hilo, así como de esta publicación de blog .

Primero, creé un CustomErrorControllerSpring que buscará para asignar cualquier error.

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

En segundo lugar, creé una CustomHttpErrorResponseclase para devolver el error como 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
}

Finalmente, tuve que apagar Whitelabel en el application.propertiesarchivo.

server.error.whitelabel.enabled=false

Esto incluso debería funcionar para xmlsolicitudes / respuestas. Pero no he probado eso. Hizo exactamente lo que estaba buscando ya que estaba creando una API RESTful y solo quería devolver JSON.

DJ House
fuente
2

server.error.whitelabel.enabled = false

Incluya la línea anterior a las carpetas de recursos application.properties

Más resolución de problema de error, consulte http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-customize-the-whitelabel-error-page

suganya sudarsan
fuente
Intenté application.properties en mi carpeta de instalación que no hizo nada. La carpeta application.properties en / src / main / resources es lo que suganya sudarsan intentaba transmitir. Parece ser una "lectura en caliente" en Eclipse también.
Richard Bradley Smith
1

Estaba tratando de llamar a un punto final REST desde un microservicio y estaba usando el método put de resttemplate .

En mi diseño si se ha producido algún error en el interior del RESTO punto final que debe devolver una respuesta de error de JSON, que estaba trabajando para algunas llamadas, pero no para este puesto uno, volvió la página de error de marca blanca en su lugar.

Así que investigué un poco y descubrí eso;

Spring intenta entender a la persona que llama si es una máquina y luego devuelve la respuesta JSON o si se trata de un navegador que devuelve el HTML de la página de error de etiqueta blanca .

Como resultado: mi aplicación cliente necesitaba decirle al punto final REST que la persona que llama es una máquina, no un navegador, por lo que para esto la aplicación cliente necesitaba agregar ' application / json ' en el encabezado ACCEPT explícitamente para el método 'put' de la nueva plantilla. Agregué esto al encabezado y resolví el problema.

mi llamada al punto final:

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

para la llamada anterior tuve que agregar debajo del parámetro de encabezado.

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

o traté de cambiar poner a cambio también, en este caso, la llamada de intercambio agregó el mismo encabezado para mí y resolvió el problema también, pero no sé por qué :)

restTemplate.exchange(....)
cazador
fuente
0

Spring Boot por defecto tiene una página de error de " etiqueta blanca " que puede ver en un navegador si encuentra un error del servidor. Whitelabel Error Page es una página genérica de error de Spring Boot que se muestra cuando no se encuentra una página de error personalizada.

Establezca "server.error.whitelabel.enabled = false" para cambiar de la página de error predeterminada

shatakshi
fuente
0

Tenía un mensaje de error WhiteLabel de problema similar en mi Angular SPA cada vez que hacía una actualización.

La solución fue crear un controlador que implemente ErrorController pero en lugar de devolver una Cadena, tuve que devolver un objeto ModelAndView que reenvía a /

@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;
    }
}
Shubhashish Mishra
fuente