Play 프레임워크의 예외 및 오류 처리

(Play Framework에서 예외를 처리하는 방법)[ https://petrepopescu.tech/2021/03/handling-exceptions-and-errors-in-play-framework/ ]

프로그래밍할 때 항상 예외를 고려하는 것이 중요합니다. 코드가 아무리 훌륭하더라도 예외를 유발할 수 있는 다른 라이브러리의 사용자 문제로 인해 항상 유효하지 않은 데이터가 있을 수 있습니다. 또한 이 메커니즘을 사용하면 잘못된 흐름을 가능한 한 빨리 종료하는 쉬운 방법입니다. 예외는 정상이며 모든 서비스에서 처리되어야 합니다. 예외의 경우에도 사용자에게 응답을 제공하여 요청이 실제로 처리되었지만 뭔가 잘못되었다는 것을 알 수 있도록 해야 합니다. 이 기사에서는 Play Framework에서 예외를 처리하는 방법과 클라이언트에 응답하는 방법을 설명합니다.

HttpErrorHandler



Play Framework는 모든 예외 처리기에 의해 구현되어야 하는 HttpErrorHandler 인터페이스를 제공합니다. 이 인터페이스에는 두 가지 방법이 있으며 둘 다 제대로 구현해야 합니다. 하나는 클라이언트의 오류(예: 잘못된 끝점에 액세스)를 처리하고 다른 하나는 서버 측에서 발생한 예외를 처리합니다.

public class ErrorHandler implements HttpErrorHandler {
    @Override
    public CompletionStage<Result> onClientError(Http.RequestHeader request, int statusCode, String message) {
        // Implementation
    }

    @Override
    public CompletionStage<Result> onServerError(Http.RequestHeader request, Throwable exception) {
        // Implementation
    }
}


클라이언트 오류의 경우 상태 코드와 오류 메시지가 포함된 Json 문자열을 반환해 보겠습니다. onClientError 메서드는 필요한 모든 정보를 제공하며 결과로 CompletebleFuture를 반환할 수 있습니다.

public class ErrorHandler implements HttpErrorHandler {
    @Override
    public CompletionStage<Result> onClientError(Http.RequestHeader request, int statusCode, String message) {
        Map<String, Object> response = new HashMap<>();
        response.put("status", statusCode);
        response.put("error", message);
        return CompletableFuture.completedFuture(
                Results.status(statusCode, Json.toJson(response))
        );
    }

    @Override
    public CompletionStage<Result> onServerError(Http.RequestHeader request, Throwable exception) {
        return null;
    }
}


서버 오류는 대부분의 마법이 일어나는 곳입니다. 코드에서 포착되지 않은 모든 예외는 결국 이 메서드에 도달하므로 여기에서 모든 것을 적절하게 처리하는 것이 중요합니다. 예외를 기록하고 클라이언트에 적절한 응답을 반환해야 합니다. 이전 방법과 마찬가지로 Json String을 반환합니다. 그러나 이 문자열을 얻는 방법은 조금 더 복잡할 수 있습니다.

나는 일반적으로 필요한 정보를 포함하는 하나 이상의 사용자 정의 예외를 정의합니다. 이 예에서는 추가 처리가 필요하지 않음을 알리고 클라이언트에 응답을 다시 반환하기 위해 서비스의 특정 부분에 throw하는 PlatformException을 만들 것입니다.

public class PlatformException extends Exception {
    private String message;
    private String errorCode;

    public PlatformException(String message, String errorCode) {
        this.message = message;
        this.errorCode = errorCode;
    }

    public PlatformException(String message, String errorCode, Throwable throwable) {
        super(throwable);
        this.message = message;
        this.errorCode = errorCode;
    }

    // Getters
}


이제 오류 처리기에서 이 예외가 발생하면 이 오류에서 얻은 JSON 문자열과 함께 500 응답을 반환합니다. 사용자 정의 예외가 아닌 경우 항상 표준 형식으로 메시지를 더 쉽게 반환할 수 있도록 예외를 만듭니다.

public class ErrorHandler implements HttpErrorHandler {
    private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());

    @Override
    public CompletionStage<Result> onClientError(Http.RequestHeader request, int statusCode, String message) {
        Map<String, Object> response = new HashMap<>();
        response.put("status", statusCode);
        response.put("error", message);
        return CompletableFuture.completedFuture(
                Results.status(statusCode, Json.toJson(response))
        );
    }

    @Override
    public CompletionStage<Result> onServerError(Http.RequestHeader request, Throwable exception) {
        LOGGER.error("Error encountered.", exception);
        Throwable exceptionToReturn = exception;
        if (!(exception instanceof PlatformException)) {
            exceptionToReturn = new PlatformException(exception.getMessage(), "UNKNOWN", exception);
        }
        return CompletableFuture.completedFuture(
                Results.internalServerError(Json.toJson(exceptionToReturn))
        );
    }
}


마지막으로 오류 처리기에 대해 Play에 알려야 합니다. 이를 위해 application.conf 파일을 편집하고 play.http.errorHandler 구성 변수를 클래스 이름으로 설정합니다.

play.http.errorHandler = "ErrorHandler"


뭐! 전체 스택 추적이 반환됩니까?



이 코드를 실행하면 JSON에 전체 스택 추적이 포함되어 있음을 알 수 있습니다. 이것은 너무 많은 정보를 제공할 수 있으므로 바람직하지 않습니다. 클라이언트가 이 모든 것을 알 필요는 없으므로 코드를 개선해 보겠습니다. 첫째, 예외 자체에서 JSON을 만들지 않습니다. 대신 메시지, 오류 코드 및 기타 필요한 정보를 포함하는 ErrorDTO를 만듭니다. 이제 예외가 발생하면 필요한 최소한의 정보만 반환됩니다.

public class ErrorHandler implements HttpErrorHandler {
    private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());

    @Override
    public CompletionStage<Result> onClientError(Http.RequestHeader request, int statusCode, String message) {
        Map<String, Object> response = new HashMap<>();
        response.put("status", statusCode);
        response.put("error", message);
        return CompletableFuture.completedFuture(
                Results.status(statusCode, Json.toJson(response))
        );
    }

    @Override
    public CompletionStage<Result> onServerError(Http.RequestHeader request, Throwable exception) {
        LOGGER.error("Error encountered.", exception);
        ErrorDTO error;
        if (exception instanceof PlatformException) {
           errorDTO = new ErrorDTO(exception.getMessage(), ((PlatformException) exception).getErrorCode());
        } else {
            errorDTO = new ErrorDTO(exception.getMessage(), "UNKNOWN");
        }
        return CompletableFuture.completedFuture(
                Results.internalServerError(Json.toJson(errorDTO))
        );
    }
}


(Play Framework에서 예외를 처리하는 방법)[ https://petrepopescu.tech/2021/03/handling-exceptions-and-errors-in-play-framework/ ]

좋은 웹페이지 즐겨찾기