Post

예외처리, RestController Advice

에러가 생길 부분을 미리 예측하여 catch, throw하고 만약 client에게까지 보여져야 하는 error이라면 controller에까지 반영한다.

✅ ExceptionControllerAdvice는 AOP를 기반으로 한다.

AOP는 서로 비슷한 코드를 여러번 반복해서 입력하는 것이 아니라
반복되는 코드끼리 모듈화해서 advice로 만들어 침투적용하는 것을 의미한다.
따라서 에외 처리 하는 코드는 반복되니까 ExceptionControllerAdvice로 빼서 적용시킨다.

✅ Advice 없이 예외처리해보기

ticketType 잘못 입력하면 error

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//controller
    @GetMapping("/tickets")
    public ResponseEntity findAirlineTickets(@RequestParam("user-id") Integer userId,
                                             @RequestParam("airline-ticket-type") String ticketType ){

        try{
            List<Ticket> tickets = airReservationService.findUserFavoritePlaceTicket(userId, ticketType);
            TicketResponse ticketResponse= new TicketResponse(tickets);
            return new ResponseEntity( ticketResponse, HttpStatus.OK); //tryCatch 할 때는 ResponseEntity를 사용
        } catch(InvalidValueExceptions ive){
            log.error("Problem in Client Request_wrong: ticket type", ive.getMessage());
            return new ResponseEntity(ive.getMessage(), HttpStatus.BAD_REQUEST);
        }
    }

//exceptions
public class InvalidValueExceptions extends RuntimeException{

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

//service
    public List<Ticket> findUserFavoritePlaceTicket(Integer userId, String ticketType) {
        //만약 ticketType이 왕복 또는 편도가 아니라면?
        Set<String> ticketTypeSet= new HashSet<>(Arrays.asList("편도", "왕복"));
        if (!ticketTypeSet.contains(ticketType))
            throw new InvalidValueExceptions(ticketType + "No such ticket Type");

        UserEntity userEntity = userRepository.findUserById(userId);
        String likePlace= userEntity.getLikeTravelPlace();

        List<AirlineTicket> airlineTickets= airlineTicketRepository.findAllAirlineTicketsWithPlaceAndTicketType(likePlace, ticketType);

        List<Ticket> tickets= airlineTickets.stream().map(Ticket::new).collect(Collectors.toList());
        return tickets;
    }

스크린샷 2024-01-16 오후 1 35 35

스크린샷 2024-01-16 오후 1 36 08

✅ @ RestController Advice

web layer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//service
    public List<Ticket> findUserFavoritePlaceTicket(Integer userId, String ticketType) {
        //만약 ticketType이 왕복 또는 편도가 아니라면?
        Set<String> ticketTypeSet= new HashSet<>(Arrays.asList("편도", "왕복"));
        if (!ticketTypeSet.contains(ticketType))
            throw new InvalidValueExceptions(ticketType + "No such ticket Type"); //⭐️throw하면 advice로 간다.

        UserEntity userEntity = userRepository.findUserById(userId).orElseThrow(
                () -> new NotFoundException("No Such User with ID" + userId));
        String likePlace= userEntity.getLikeTravelPlace();

        List<AirlineTicket> airlineTickets= airlineTicketRepository.findAllAirlineTicketsWithPlaceAndTicketType(likePlace, ticketType);

        if(airlineTickets.isEmpty()) throw new NotFoundException("No matching likeplace and ticketType Found");

        List<Ticket> tickets= airlineTickets.stream().map(Ticket::new).collect(Collectors.toList());
        return tickets;
    }

//기존 코드
//controller
    @GetMapping("/tickets")
    public ResponseEntity findAirlineTickets(@RequestParam("user-id") Integer userId,
                                             @RequestParam("airline-ticket-type") String ticketType ){

        try{
            List<Ticket> tickets = airReservationService.findUserFavoritePlaceTicket(userId, ticketType);
            TicketResponse ticketResponse= new TicketResponse(tickets);
            return new ResponseEntity( ticketResponse, HttpStatus.OK); //tryCatch 할 때는 ResponseEntity를 사용
        } catch(InvalidValueExceptions ive){
            log.error("Problem in Client Request_wrong: ticket type", ive.getMessage());
            return new ResponseEntity(ive.getMessage(), HttpStatus.BAD_REQUEST);
        } catch(NotFoundException nfe){
            log.error("Problem in DB: wrong User", nfe.getMessage());
            return new ResponseEntity( nfe.getMessage(), HttpStatus.NOT_FOUND);
        }
    }

⭐️ ExceptionControllerAdvice

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//
    @PostMapping("/reservation")
    @ResponseStatus(HttpStatus.CREATED)
    public ReservationResult makeReservation(@RequestBody ReservationRequest reservationRequest){

            ReservationResult reservationResult= airReservationService.makeReservation(reservationRequest);
            return reservationResult;

        //⭐️ NotAcceptException catch 삭제하고 ExceptionControllerAdvice에 위임
        //⭐️ NotFoundException catch 삭제하고 ExceptionControllerAdvice에 위임
    }
//ExceptionControllerAdvice
@Slf4j
@RestControllerAdvice
public class ExceptionControllerAdvice {
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ExceptionHandler(NotFoundException.class)
    public String handleNotFoundException(NotFoundException nfe){
        log.error("Problem in DB: wrong User"+  nfe.getMessage());
        return nfe.getMessage();
    }
    @ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
    @ExceptionHandler(NotAccpetExcpetion.class)
    public String handleNotAcceptException(NotAccpetExcpetion nae){
        log.error("Problem in client", nae.getMessage());
        return nae.getMessage();
    }
}

This post is licensed under CC BY 4.0 by the author.