1️⃣ Passo: Tratando erros de validação simples
Objetivo: Tratar erros de validação e retornar uma resposta personalizada no formato JSON.
- Crie o @RestControllerAdvicepara tratar exceções de validação.
Exemplo:
   @RestControllerAdvice
   public class GlobalExceptionHandler {
       @ExceptionHandler(MethodArgumentNotValidException.class)
       @ResponseStatus(HttpStatus.BAD_REQUEST)
       public ErrorResponse handleValidationException(MethodArgumentNotValidException ex) {
           List<FieldErrorResponse> fieldErrors = ex.getBindingResult().getFieldErrors()
               .stream()
               .map(error -> new FieldErrorResponse(error.getField(), error.getDefaultMessage()))
               .collect(Collectors.toList());
           return new ErrorResponse(List.of(), fieldErrors, fieldErrors.size());
       }
   }
- Crie a classe ErrorResponseeFieldErrorResponse.
Exemplo:
   public record ErrorResponse(
       List<String> globalErrorMessages,
       List<FieldErrorResponse> errors,
       int numberOfErrors
   ) {}
   public record FieldErrorResponse(String field, String message) {}
- Resultado de erro no formato JSON:
   {
     "globalErrorMessages": [],
     "errors": [
       {
         "field": "email",
         "message": "must not be blank"
       }
     ],
     "numberOfErrors": 1
   }
  
  
  2️⃣ Passo: Adicionando Mensagens de Erro com MessageSource (Internacionalização)
Objetivo: Configurar internacionalização e personalizar as mensagens de erro.
- Crie o arquivo de mensagens messages.properties.
Exemplo (src/main/resources/messages.properties):
   error.notblank = O campo {0} não pode estar em branco.
   error.invalid = O valor informado para {0} é inválido.
   error.internal = Ocorreu um erro interno. Tente novamente mais tarde.
- Configure o MessageSourceno Spring.
Criação da classe MessageSourceConfig:
   @Configuration
   public class MessageSourceConfig {
       @Bean
       public MessageSource messageSource() {
           ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
           messageSource.setBasename("classpath:messages");
           messageSource.setDefaultEncoding("UTF-8");
           return messageSource;
       }
       @Bean
       public LocaleResolver localeResolver() {
           SessionLocaleResolver localeResolver = new SessionLocaleResolver();
           localeResolver.setDefaultLocale(Locale.forLanguageTag("pt-BR"));
           return localeResolver;
       }
       @Bean
       public LocaleChangeInterceptor localeChangeInterceptor() {
           LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
           localeChangeInterceptor.setParamName("lang");
           return localeChangeInterceptor;
       }
   }
- Uso do MessageSourceno@RestControllerAdvicepara mensagens de erro personalizadas.
Modifique o código do @RestControllerAdvice para usar o MessageSource:
   @RestControllerAdvice
   public class GlobalExceptionHandler {
       private final MessageSource messageSource;
       public GlobalExceptionHandler(MessageSource messageSource) {
           this.messageSource = messageSource;
       }
       @ExceptionHandler(MethodArgumentNotValidException.class)
       @ResponseStatus(HttpStatus.BAD_REQUEST)
       public ErrorResponse handleValidationException(MethodArgumentNotValidException ex, Locale locale) {
           List<FieldErrorResponse> fieldErrors = ex.getBindingResult().getFieldErrors()
               .stream()
               .map(error -> new FieldErrorResponse(
                   error.getField(),
                   messageSource.getMessage(error.getDefaultMessage(), new Object[]{error.getField()}, locale)
               ))
               .collect(Collectors.toList());
           return new ErrorResponse(List.of(), fieldErrors, fieldErrors.size());
       }
   }
- Resultado de erro internacionalizado em português (pt):
   {
     "globalErrorMessages": [],
     "errors": [
       {
         "field": "email",
         "message": "O campo email não pode estar em branco."
       }
     ],
     "numberOfErrors": 1
   }
  
  
  3️⃣ Passo: Tratando Exceções Genéricas com @ExceptionHandler(Exception.class)
Objetivo: Capturar qualquer exceção inesperada e retornar uma resposta personalizada.
- Adicione o tratamento de exceções genéricas para capturar erros não esperados.
Exemplo:
   @RestControllerAdvice
   public class GlobalExceptionHandler {
       private final MessageSource messageSource;
       public GlobalExceptionHandler(MessageSource messageSource) {
           this.messageSource = messageSource;
       }
       @ExceptionHandler(MethodArgumentNotValidException.class)
       @ResponseStatus(HttpStatus.BAD_REQUEST)
       public ErrorResponse handleValidationException(MethodArgumentNotValidException ex, Locale locale) {
           List<FieldErrorResponse> fieldErrors = ex.getBindingResult().getFieldErrors()
               .stream()
               .map(error -> new FieldErrorResponse(
                   error.getField(),
                   messageSource.getMessage(error.getDefaultMessage(), new Object[]{error.getField()}, locale)
               ))
               .collect(Collectors.toList());
           return new ErrorResponse(List.of(), fieldErrors, fieldErrors.size());
       }
       @ExceptionHandler(Exception.class)
       @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
       public ErrorResponse handleGenericException(Exception ex) {
           List<String> globalErrors = List.of("Ocorreu um erro inesperado. Contate o suporte.");
           return new ErrorResponse(globalErrors, List.of(), 1);
       }
   }
- Resultado de erro genérico (quando ocorre uma exceção inesperada):
   {
     "globalErrorMessages": [
       "Ocorreu um erro inesperado. Contate o suporte."
     ],
     "errors": [],
     "numberOfErrors": 1
   }
4️⃣ Passo: Permitir a Troca de Idioma com Parâmetro na URL
Objetivo: Permitir que o idioma da aplicação seja alterado via parâmetro na URL.
- Adicione o LocaleResolvereLocaleChangeInterceptorpara permitir a troca de idioma.
Já configurado na classe MessageSourceConfig:
   @Bean
   public LocaleResolver localeResolver() {
       SessionLocaleResolver localeResolver = new SessionLocaleResolver();
       localeResolver.setDefaultLocale(Locale.forLanguageTag("pt-BR"));
       return localeResolver;
   }
   @Bean
   public LocaleChangeInterceptor localeChangeInterceptor() {
       LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
       localeChangeInterceptor.setParamName("lang");
       return localeChangeInterceptor;
   }
- 
Testar a troca de idioma na URL:
- Requisição com idioma português: GET /minha-rota?lang=pt
- Requisição com idioma inglês: GET /minha-rota?lang=en
 
- Requisição com idioma português: 
📌 Conclusão:
Agora você tem uma aplicação que:
- Captura erros de validação e os retorna no formato JSON personalizado.
- 
Personaliza mensagens de erro usando internacionalização (MessageSource).
- Captura exceções genéricas e retorna uma resposta consistente para erros inesperados.
- Permite trocar o idioma da aplicação dinamicamente via parâmetro na URL.
Esses passos podem ser expandidos conforme a necessidade de sua aplicação, mas com esses fundamentos, você já tem uma base sólida para tratar erros de maneira organizada, escalável e amigável ao usuário. 🚀
 

 
    
Top comments (0)