Página de erro do Spring Boot Remove Whitelabel

156

Estou tentando remover a página de erro de etiqueta branca, então o que fiz foi criar um mapeamento de controlador para "/ error",

@RestController
public class IndexController {

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

}

Mas agora estou recebendo esse erro.

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

Não sei se estou fazendo algo errado. Conselho por favor.

EDITAR:

Já foi adicionado error.whitelabel.enabled=false ao arquivo application.properties, ainda obtendo o mesmo erro

Yasitha Waduge
fonte
1
Veja este projeto , github.com/paulc4/mvc-exceptions/blob/master/src/main/java/… , parece que eles têm uma página de erro remapeando nele.
Innot Kauker
Você já tentou configurar spring.resources.add-mappings=false?
precisa saber é
Obrigado pela sugestão, sim ainda tenho o mesmo erro
Yasitha Waduge
Você está apenas tentando retornar algum conteúdo personalizado quando o /errorcaminho é chamado?
precisa saber é

Respostas:

240

Você precisa alterar seu código para o seguinte:

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

Seu código não funcionou, porque o Spring Boot registra automaticamente o BasicErrorControllerSpring Bean quando você não especificou uma implementação de ErrorController.

Para ver esse fato, basta navegar até ErrorMvcAutoConfiguration.basicErrorController aqui .

geo e
fonte
1
Deparou-se com o mesmo problema, procurei nos documentos do Spring, mas ele não mencionou o BasicErrorController. Isso funciona :)
Mike R
4
Eu tive que ir através da fonte para encontrar este :-)
geoand
1
Obrigado, funcionou bem! Um pequeno acompanhamento, se você puder dar alguma indicação: digamos que entramos nesse manipulador de erros porque alguma exceção foi lançada em nosso aplicativo (e o Spring define implicitamente o código de resposta como 500, o que está correto); existe uma maneira fácil de se apossar dessa exceção aqui (para incluir alguns detalhes na mensagem de erro retornada)?
Jonik
1
Que bom que você achou útil! Embora eu não tenha tentado, tenho certeza de que você pode usar os princípios encontrados no Spring Boot BasicErrorController(consulte github.com/spring-projects/spring-boot/blob/… ) para realizar o que deseja
geo e
3
Hmm, sim, obrigado novamente! No começo, eu não tinha certeza de como obter esse ErrorAttributesobjeto (contendo os detalhes do erro), mas tentei simplesmente @Automando-o e ele funciona. O que eu fiz por agora: gist.github.com/jonikarppinen/662c38fb57a23de61c8b
Jonik
44

Se você quiser uma página de resposta mais "JSONish", tente algo assim:

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
fonte
7
No Spring-Boot v2, as classes ErrorController e ErrorAttributes estão no pacote org.springframework.boot.web.servlet.error e, além disso, a assinatura do método ErrorAttributes # getErrorAttributes foi alterada, observe a dependência do Spring-Boot v1 e, possivelmente, dê dicas para a v2, THX.
Chrisinmtown 13/11/19
1
Alteração: mapa privado <String, Objeto> getErrorAttributes (HttpServletRequest aRequest, includeStackTrace booleano) {RequestAttributes requestAttributes = new ServletRequestAttributes (aRequest); retornar errorAttributes.getErrorAttributes (requestAttributes, includeStackTrace); } Por: private Map <String, Object> getErrorAttributes (solicitação HttpServletRequest, booleana includeStackTrace) {WebRequest webRequest = new ServletWebRequest (request); retorne this.errorAttributes.getErrorAttributes (webRequest, includeStackTrace); }
Rija Ramampiandra 24/04/19
2
Uma versão atualizada do SimpleErrorController.java considerando os comentários do acima podem ser encontrados aqui> gist.github.com/oscarnevarezleal/...
Oscar Nevarez
38

O documento de inicialização do Spring 'estava' errado (eles o corrigiram):

Para desligá-lo, você pode definir error.whitelabel.enabled = false

deveria estar

Para desativá -lo, você pode definir server.error.whitelabel.enabled = false

Willome
fonte
Isso desativará a Página de erro de etiqueta branca, mas a inicialização por primavera mapeará o terminal de /errorqualquer maneira. Para liberar o /errorconjunto de terminais server.error.path=/error-springou algum caminho alternativo.
notas-jj
32

Você pode removê-lo 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 { ... }

No entanto, observe que isso provavelmente fará com que as páginas de whitelabel do contêiner do servlet sejam exibidas :)


EDIT: Outra maneira de fazer isso é via application.yaml. Basta colocar o valor:

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

Documentação

Para Spring Boot <2.0, a classe está localizada no pacote org.springframework.boot.autoconfigure.web.

hoodieman
fonte
15

Manual aqui diz que você tem que definir server.error.whitelabel.enabledpara falsedesativar a página de erro padrão. Talvez seja o que você quer?

Estou enfrentando o mesmo erro depois de adicionar / mapeamento de erros, a propósito.

Innot Kauker
fonte
Sim, eu já definiu error.whitelabel.enabled = false mas ainda recebendo o mesmo erro após o mapeamento acrescentando / erro
Yasitha Waduge
Isso desativará a Página de erro de etiqueta branca, mas a inicialização por primavera mapeará o terminal de /errorqualquer maneira. Para liberar o /errorconjunto de terminais server.error.path=/error-springou algum caminho alternativo.
notas-jj
11

Com o Spring Boot> 1.4.x, você pode fazer o seguinte:

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

mas, em caso de exceção, o contêiner do servlet exibirá sua própria página de erro.

db80
fonte
8

Isso depende da sua versão de inicialização por mola:

Quando SpringBootVersion <= 1.2, useerror.whitelabel.enabled = false

Quando SpringBootVersion > = 1.3, useserver.error.whitelabel.enabled = false

sendon1982
fonte
6

No Spring Boot 1.4.1 usando modelos de bigode, colocar error.html na pasta de modelos será suficiente:

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

Variáveis ​​adicionais podem ser passadas criando um interceptor para /error

Ecmel Ercan
fonte
3

Aqui está um método alternativo muito semelhante à "maneira antiga" de especificar mapeamentos de erros no web.xml.

Basta adicionar isso à sua configuração do 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"));
    }

}

Em seguida, você pode definir as páginas de erro no conteúdo estático normalmente.

O personalizador também pode ser um separado @Component, se desejado.

rustyx
fonte
3

Estou usando o Spring Boot versão 2.1.2 e a errorAttributes.getErrorAttributes()assinatura não funcionou para mim (na resposta de acohen). Como eu queria uma resposta do tipo JSON, fiz uma pequena pesquisa e descobri que esse método fazia exatamente o que eu precisava.

Eu obtive a maioria das minhas informações neste tópico e também nesta postagem do blog .

Primeiro, criei um CustomErrorControllerque o Spring procurará mapear para qualquer erro.

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

Segundo, criei uma CustomHttpErrorResponseclasse para retornar o erro 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, tive que desligar o Whitelabel no application.propertiesarquivo.

server.error.whitelabel.enabled=false

Isso deve funcionar mesmo para xmlsolicitações / respostas. Mas eu não testei isso. Ele fez exatamente o que estava procurando desde que estava criando uma API RESTful e só queria retornar JSON.

DJ House
fonte
2

server.error.whitelabel.enabled = false

Inclua a linha acima nas pastas Resources application.properties

Para solucionar mais problemas, consulte http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-customize-the-whitelabel-error-page

suganya sudarsan
fonte
Eu tentei application.properties na minha pasta de instalação que não fez nada. A pasta application.properties em / src / main / resources é o que suganya sudarsan estava tentando transmitir. Parece ser uma "leitura quente" no Eclipse também.
Richard Bradley Smith
1

Eu estava tentando chamar um ponto de extremidade REST de um microsserviço e estava usando o método put resttemplate método .

No meu design, se ocorreu algum erro dentro do terminal REST, ele deveria retornar uma resposta de erro JSON, estava funcionando para algumas chamadas, mas não para esta, coloquei uma, retornou a página de erro de etiqueta branca em seu lugar.

Então eu fiz algumas investigações e descobri isso;

O Spring tenta entender o responsável pela chamada se for uma máquina e, em seguida, ele retornará a resposta JSON ou, se for um navegador, retornará o HTML da página de erro da etiqueta branca .

Como resultado: meu aplicativo cliente precisava dizer ao ponto de extremidade REST que o chamador é uma máquina, não um navegador. Para isso, o aplicativo cliente precisava adicionar ' application / json ' ao cabeçalho ACCEPT explicitamente para o método 'put' do restante do modelo. Eu adicionei isso ao cabeçalho e resolvi o problema.

minha chamada para o endpoint:

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

para a chamada acima, eu tive que adicionar abaixo os parâmetros do cabeçalho.

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

ou tentei alterar também o put to exchange, nesse caso, a chamada de troca adicionou o mesmo cabeçalho para mim e resolveu o problema também, mas não sei por que :)

restTemplate.exchange(....)
cazador
fonte
0

O Spring Boot por padrão possui uma página de erro " whitelabel " que você pode ver em um navegador se encontrar um erro no servidor. Página de erro Whitelabel é uma página de erro genérica do Spring Boot que é exibida quando nenhuma página de erro personalizada é encontrada.

Defina “server.error.whitelabel.enabled = false” para alternar da página de erro padrão

shatakshi
fonte
0

Eu tive um problema semelhante com a mensagem de erro WhiteLabel no meu SPA Angular sempre que fazia uma atualização.

A correção foi criar um controlador que implementa ErrorController, mas, em vez de retornar uma String, tive que retornar um objeto ModelAndView que encaminha para /

@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
fonte