web-dev-qa-db-fra.com

Comment renvoyer une exception dans JSON dans Spring Boot

J'ai un mappage de demandes - 

  @RequestMapping("/fetchErrorMessages")
  public @ResponseBody int fetchErrorMessages(@RequestParam("startTime") String startTime,@RequestParam("endTime") String endTime) throws Exception
  {
      if(SanityChecker.checkDateSanity(startTime)&&SanityChecker.checkDateSanity(endTime))
      {
          return 0;
      }
      else
      {
          throw new NotFoundException("Datetime is invalid");
      }
  }

Si startTime et endTime ne sont pas valides, je souhaite générer une erreur 500 mais renvoyer la chaîne d'exception au format JSON. Cependant, je reçois une page HTML à la place disant 

Whitelabel Error Page

Cette application n'a pas de mappage explicite pour/error, vous la voyez donc comme une solution de secours.

Mer. 20 déc. 10:49:37 IST 2017
Une erreur inattendue s'est produite (type = erreur interne du serveur, statut = 500).
Date/heure est invalide

Au lieu de cela, je voulais retourner 500 avec un JSON 

{"error":"Date time format is invalid"}

Comment puis-je m'y prendre?

6
Prateek Narendra

Supposons que vous ayez une classe d'exception personnalisée NotFoundException et ses implémentations qui ressemblent à ceci:

public class NotFoundException extends Exception {

    private int errorCode;
    private String errorMessage;

    public NotFoundException(Throwable throwable) {
        super(throwable);
    }

    public NotFoundException(String msg, Throwable throwable) {
        super(msg, throwable);
    }

    public NotFoundException(String msg) {
        super(msg);
    }

    public NotFoundException(String message, int errorCode) {
        super();
        this.errorCode = errorCode;
        this.errorMessage = message;
    }


    public void setErrorCode(int errorCode) {
        this.errorCode = errorCode;
    }

    public int getErrorCode() {
        return errorCode;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    @Override
    public String toString() {
        return this.errorCode + " : " + this.getErrorMessage();
    }
}

Maintenant, vous voulez lancer une exception du contrôleur. Si vous lancez une exception, vous devez la récupérer dans une classe standard Error Handler. Supposons qu'au printemps, elles fournissent l'annotation @ControllerAdvice à appliquer pour créer une classe Standard Error Handler. Lorsqu'il est appliqué à une classe, alors ce composant de ressort (je veux dire la classe que vous avez annotée) peut intercepter toute exception levée par le contrôleur. Mais nous devons mapper la classe des exceptions avec la méthode appropriée. Nous avons donc défini une méthode avec votre gestionnaire NotFoundException d'exception, comme ci-dessous.

@ControllerAdvice
public class RestErrorHandler {

    @ExceptionHandler(NotFoundException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public Object processValidationError(NotFoundException ex) {
        String result = ex.getErrorMessage();
        System.out.println("###########"+result);
        return ex;
    }
}

Vous voulez envoyer le statut http au serveur interne error (500) , nous avons donc utilisé @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR). Puisque vous avez utilisé Spring-boot, vous n'avez donc pas besoin de créer une chaîne json, à l'exception d'une simple annotation @ResponseBody qui peut le faire pour vous automatiquement.

4
Ataur Rahman Munna

Créez une exception personnalisée.

public class SecurityException extends RuntimeException {

    private static final long serialVersionUID = -7806029002430564887L;

    private String message;

    public SecurityException() {
    }

    public SecurityException(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

}

Créez une entité de réponse personnalisée.

public class SecurityResponse {

    private String error;

    public SecurityResponse() {

    }

    public SecurityResponse(String error) {
        this.error = error;
    }

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }

}

Créez un ControllerAdvice avec ExceptionHandler pour une exception personnalisée. Il gérera l'exception personnalisée, sera rempli et retournera la réponse personnalisée comme indiqué ci-dessous.

@ControllerAdvice
public class SecurityControllerAdvice {

    @ExceptionHandler(SecurityException.class)
    @ResponseBody
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public SecurityResponse handleSecurityException(SecurityException se) {
        SecurityResponse response = new SecurityResponse(se.getMessage());
        return response;
    }
}

Lancez l'exception personnalisée en fonction de votre condition.

throw new SecurityException("Date time format is invalid");

Maintenant, lancez et testez votre application. PAR EXEMPLE. :

 enter image description here

3
Neeraj Benjwal

vous pouvez créer la classe NotFoundException avec l'annotation @ResponseStatus comme ci-dessous:

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public class NotFoundException extends RuntimeException {
   public NotFoundException() {
   }

   public NotFoundException(String message) {
    super(message);
   }

}
1
Hiren

Javax a un nom d'interface comme ExceptionMapper. Veuillez vous référer à l'extrait de code ci-dessous. Pour chaque exception RuntimeException de votre application, il sera mappé à une entité Json Response.

public class RuntimeExceptionMapper implements ExceptionMapper <RuntimeException> {

@Override
public Response toResponse(RuntimeException exception) {
    ErrorResponse errorResponse = new ErrorResponse();
    errorResponse.setMessage(exception.getMessage);
    if (exception== null) {
        logger.error("Exception Details Not found");            
    } else {
        return Response.status(Status.INTERNAL_SERVER_ERROR)
            .entity(errorResponse )
                .type(MediaType.APPLICATION_JSON)
                    .header("trace-id", "1234").build();
    }


}

}

1
Mohit Sharma

Voici comment je l'ai fait dans ma candidature:

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class ExceptionHandlingControllerAdvice {

   @ExceptionHandler(ExecutionRestrictionViolationException.class)
   public ResponseEntity<String> handleExecutionRestrictionViolationException(ExecutionRestrictionViolationException ex) {
     return response("Invalid Query", ex.getMessage(), HttpStatus.UNPROCESSABLE_ENTITY);
   }

   private static String createJson(String message, String reason) {
    return "{\"error\" : \"" + message + "\"," +
            "\"reason\" : \"" + reason  + "\"}";
   }

   private static ResponseEntity<String> response(String message,
                                               String reason,
                                               HttpStatus httpStatus) {
    String json = createJson(message, reason);
    return new ResponseEntity<>(json, httpStatus);
   }

}

Explication:

  1. Vous créez un conseil de contrôleur, vous le marquez avec une annotation spéciale et vous le définissez comme tout autre bean (dans mon cas, il s'agissait d'une configuration Java, mais cela n'a pas vraiment d'importance)

  2. Pour chaque exception que vous souhaitez gérer comme ceci - définissez un gestionnaire qui générera une réponse dans le format de votre choix

  3. Il existe une méthode statique createJson - vous pouvez utiliser une méthode différente, cela n'a pas vraiment d'importance.

À présent, ce n’est qu’une façon de travailler (il est disponible dans les versions les plus récentes de Spring Boot) - mais il en existe d’autres:

Toutes les méthodes que je connais (et même plus) sont listées ici .

0
Mark Bramnik