web-dev-qa-db-ja.com

Spring BootでJSONに例外をスローする方法

リクエストマッピングがあります-

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

StartTimeとendTimeが無効な場合、500エラーをスローしますが、JSONで例外文字列を返します。ただし、代わりにHTMLページが表示されます

ホワイトラベルエラーページ

このアプリケーションには/ errorの明示的なマッピングがないため、これをフォールバックと見なしています。

2017年12月20日水曜日10:49:37 IST
予期しないエラーが発生しました(タイプ=内部サーバーエラー、ステータス= 500)。
日時が無効です

代わりに、JSONで500を返したい

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

これについてどうすればいいですか?

9

カスタムExceptionクラスNotFoundExceptionがあり、その実装が次のようになっているとします。

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

ここで、コントローラーから例外をスローする必要があります。例外をスローする場合、標準エラーハンドラクラスから例外をキャッチする必要があります。たとえば、春には、クラス標準エラーハンドラを作成するために適用する_@ControllerAdvice_注釈を提供します。クラスに適用すると、このスプリングコンポーネント(注釈を付けたクラスを意味します)は、コントローラーからスローされた例外をキャッチできます。しかし、適切なメソッドで例外クラスをマッピングする必要があります。そこで、以下のような例外NotFoundExceptionハンドラーを持つメソッドを定義しました。

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

内部サーバーへのHTTPステータスエラー(500)を送信したいので、ここでは@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)を使用しました。 Spring-bootを使用したため、json文字列を作成する必要はありません。単純な注釈_@ResponseBody_を使用すると、自動的に行うことができます。

6

カスタム例外を作成します。

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

}

カスタム応答エンティティを作成します。

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

}

カスタム例外用にExceptionHandlerを使用してControllerAdviceを作成します。カスタム例外を処理し、以下のようにカスタム応答を生成して返します。

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

条件に基づいてカスタム例外をスローします。

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

次に、アプリを実行してテストします。例えば。 :

enter image description here

4
Neeraj Benjwal

これは私のアプリケーションでどのようにしたかです:

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

}

説明:

  1. コントローラーのアドバイスを作成し、特別な注釈を付けてマークし、他のBeanと同じように定義します(私の場合はJava構成でしたが、実際は重要ではありません)

  2. 各例外に対して、このように処理したい-希望する形式で応答を生成するハンドラーを定義します

  3. 静的メソッドcreateJsonがあります-別の方法を使用することもできますが、実際には問題ではありません。

現在、これは動作する1つの方法にすぎません(より最近のスプリングブートバージョンで使用可能)-しかし、他にもあります:

私が知っているすべてのメソッド(およびそれ以上)が here にリストされています。

1
Mark Bramnik

以下のような@ResponseStatusアノテーションを使用してNotFoundExceptionクラスを作成できます。

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

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

}
1
Hiren

Javaxには、ExceptionMapperというインターフェース名があります。以下のコードスニペットを参照してください。アプリケーションのすべてのRuntimeExceptionについて、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