[사이드프로젝트] 그저 그런 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.)