kok202
ControllerAdvice의 Response status 가 변경되지 않는 문제

2019. 6. 20. 14:09[개발] 기록/오늘의 고민

문제 상확을 복기하는 과정이므로 timestamp 값은 무시합니다.

문제 상황

@ControllerAdvice
public class MyControllerAdvice {
    @ResponseStatus(code = CONFLICT)
    @ExceptionHandler(MyException.class)
    public MyException myHandler(MyException ex) {
        return ex;
    }
}
결과
Status 404
Body {
    "timestamp": "2019-06-20T02:49:49.965+0000",
    "status": 404,
    "error": "Not Found",
    "message": “My exception occured!”,
    "path": “…”
}

@ResponseStatus 로 Conflict status 를 내리도록 지정했는데 404로 뜬다.

 

 

 

 

 

시도 1 : ResponseEntity 로 떨궈보자

@ControllerAdvice
public class MyControllerAdvice {
    @ResponseStatus(code = CONFLICT)
    @ExceptionHandler(MyException.class)
    public ResponseEntity<?> myHandler(MyException ex) {
        return new ResponseEntity(ex.getMessage(), CONFLICT);
    }
}
결과
Status 404
Body {
    "timestamp": "2019-06-20T02:49:49.965+0000",
    "status": 404,
    "error": "Not Found",
    "message": “My exception occured!”,
    "path": “…”
}

여전히 404

 

 

 

 

 

시도 2 : ResponseStatusException 으로 떨궈보자

@ControllerAdvice
public class MyControllerAdvice {
    @ResponseStatus(code = CONFLICT)
    @ExceptionHandler(MyException.class)
    public ResponseStatusException myHandler(MyException ex) {
        return new ResponseStatusException(CONFLICT, ex.getMessage());
    }
}
결과
Status 409
Body ”My exception occured!”

Status 는 바뀌는데 Body 가 Json 포맷이 아니다.

 

 

 

 

 

시도 3 : ResponseStatusException 을 throw 해보자

@ControllerAdvice
public class MyControllerAdvice {
    @ResponseStatus(code = CONFLICT)
    @ExceptionHandler(MyException.class)
    public void myHandler(MyException ex) {
        throw new ResponseStatusException(CONFLICT, ex.getMessage());
    }
}
결과
Status 500
Body {
    "timestamp": "2019-06-20T02:49:49.965+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": “My exception occured!”,
    "path": “…”
}

ResponseStatusException 을 핸들링하는 핸들러가 없어서 서버 에러로 뜬다.

 

 

 

 

 

시도 4 (OK) : 매개변수에  reponse 객체를 받고 강제로 Status 값을 넣어보자

@ControllerAdvice
public class MyControllerAdvice {
    @ResponseStatus(code=CONFLICT)
    @ExceptionHandler(MyException.class)
    public void myHandler(HttpServletResponse response) throws IOException{
        response.sendError(CONFLICT.value());
    }
}
결과
Status 409
Body {
    "timestamp": "2019-06-20T02:49:49.965+0000",
    "status": 409,
    "error": "Conflict",
    "message": “My exception occured!”,
    "path": “…”
}

일단 해결. 그런데 이렇게 하면 @ResponseStatus 는 필요없는 것 아닌가?

 

 

 

 

 

시도 5 (OK)

@ControllerAdvice
public class MyControllerAdvice {
    @ExceptionHandler(MyException.class)
    public void myHandler(HttpServletResponse response) throws IOException{
        response.sendError(CONFLICT.value());
    }
}
결과
Status 409
Body {
    "timestamp": "2019-06-20T02:49:49.965+0000",
    "status": 409,
    "error": "Conflict",
    "message": “My exception occured!”,
    "path": “…”
}

실제로 없어도 된다.

 

 

 

 

 

 

시도 6 : 그렇담 @ResponseStatus 의 역할은 뭐지? 왜 제대로 동작하지 않지? @ResponseStatus 의 역할이 Status 를 세팅해주는 역할이라면 response 객체를 매개변수로 받아왔으니 강제로 status 를 바꾸는 부분이 없어도 동작해야하지 않을까?

@ControllerAdvice
public class MyControllerAdvice {
    @ResponseStatus(code=CONFLICT)
    @ExceptionHandler(MyException.class)
    public void myHandler(HttpServletResponse response) throws IOException{
    }
}
결과
Status 409
Body null

status 는 바뀌는데 response body가 없다.

-> 생각 : @ResponseStatus 의 우선 순위가 낮아서 Response body 가 이미 있으면 Status 를 바꾸려 시도하지 않는건가?

참고 : @ResponseStatus 는 핸들러가 무사히 종료됬을 때 Response status 를 지정한 값으로 바꾼다.

 

진행중...