[사이드프로젝트] 그저 그런 REST API로 괜찮은가? - 진정한 REST API 구현해보기 - GET Event 구현하기
Get Event Test 작성
이번에는 단일 Event를 가져오는 로직을 구현할 것이다.
여기서 고려해야할 점은
- 단일로 불러왔을 때, HATEAOS를 만족하는가.
- 존재하지 않는 Event를 가져올 때, 에러 메시지를 보내는가.
테스트 코드를 작성하면 다음과 같다.
    @Test
    public void get_event_success() throws Exception {
        Event event = createEvent(0);
        this.eventRepository.save(event);
        mockMvc.perform(get("/api/events/{id}", event.getId()))
                .andDo(print())
                .andExpect(jsonPath("event").exists())
                .andExpect(jsonPath("_links").exists());
    }
    @Test
    public void get_event_not_found_event() throws Exception {
        //Given
        Integer wrongId = 10010;
        mockMvc.perform(get("/api/events/{id}", wrongId))
                .andDo(print())
                .andExpect(status().isNotFound())
                .andExpect(jsonPath("timestamp").exists())
                .andExpect(jsonPath("status").exists())
                .andExpect(jsonPath("error").exists())
                .andExpect(jsonPath("message").exists());
    }
Service 로직 구현
Service layer에서는 JPA를 통해서 데이터를 불러온 후, null 체크를 통해 Event가 존재하는 지 안하는 지 예외처리를 할 것이다.
JPA에서 findBy로 데이터를 가져올 시, Optional<> 객체에 담겨서 온다.
이 Optional 객체의 isEmpty()가 참일 경우, 데이터가 존재하지 않기 때문에 if문과 throw문을 통해서 예외처리를 한다.
    public Event read(Integer id){
        Optional<Event> findEvent =  this.eventRepository.findById(id);
        if(findEvent.isEmpty())
            throw new CustomException(HttpStatus.NOT_FOUND, "Event not found");
        return findEvent.get();
    }CustomException 구현 및 ErrorResponse 수정
이제 예외 처리를 할 때, Custom Error를 사용하여 내가 필요로 하는 에러를 던지려고 한다.
- CustomException.java
package com.carrykim.restapi.event.global.exception;
import lombok.Getter;
import org.springframework.http.HttpStatus;
@Getter
public class CustomException extends RuntimeException{
    private HttpStatus httpStatus;
    private String message;
    public CustomException(HttpStatus httpStatus, String message){
        this.httpStatus = httpStatus;
        this.message = message;
    }
}
- ErrorResponse.java
package com.carrykim.restapi.event.global.exception;
import lombok.Builder;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Getter
public class ErrorResponse {
    private final LocalDateTime timestamp = LocalDateTime.now();
    private int status;
    private List<String> message;
    private String error;
    public ErrorResponse(HttpStatus httpStatus , BindingResult bindingResult) {
        this.status = httpStatus.value();
        this.error = httpStatus.name();
        this.message = bindingResult.getFieldErrors().stream()
                .map(e -> {
                    String m = e.getField() + " : " + e.getDefaultMessage();
                    return m;
                })
                .collect(Collectors.toList());
    }
    public ErrorResponse(CustomException customException){
        this.status = customException.getHttpStatus().value();
        this.error = customException.getHttpStatus().name();
        this.message = new ArrayList<>();
        this.message.add(customException.getMessage());
    }
}
EventExceptionHandler 수정
이제 EventExceptionHandler를 수정해서 CustomException이 던져지면 이를 받아서 에러 메시지를 보낸다.
package com.carrykim.restapi.event.global.exception;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class EventExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity validationErrorException(final MethodArgumentNotValidException e) {
        return ResponseEntity
                .status(HttpStatus.BAD_REQUEST)
                .body(new ErrorResponse(HttpStatus.BAD_REQUEST,e.getBindingResult()));
    }
    @ExceptionHandler(CustomException.class)
    public ResponseEntity customErrorException(final CustomException e){
        return ResponseEntity
                .status(e.getHttpStatus().value())
                .body(new ErrorResponse(e));
    }
}
EventController 수정
마지막으로 Service layer에서 넘긴 Event 객체를 EventResource 객체에 담아 URI 매핑 후 반환한다.
	@GetMapping("/{id}")
    public ResponseEntity read(@PathVariable Integer id){
        Event event = this.eventService.read(id);
        EventResource eventResource = new EventResource(event);
        addLinks(eventResource);
        return ResponseEntity.ok(eventResource);
    }테스트 결과

Author And Source
이 문제에 관하여([사이드프로젝트] 그저 그런 REST API로 괜찮은가? - 진정한 REST API 구현해보기 - GET Event 구현하기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@carrykim/사이드프로젝트-그저-그런-REST-API로-괜찮은가-진정한-REST-API-구현해보기-GET-Event-구현하기저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
                                
                                
                                
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)