Skip to content

Commit

Permalink
feat : 전역적 예외처리 로직 생성 및 Success,ErrorResponse 리팩토링 (#14)
Browse files Browse the repository at this point in the history
* fix : rank 컬럼명이 mysql 예약어와 겹쳐, 임시로 ranking으로 수정 (CC-114)

* chore : jpa create option : update로 수정 (CC-114)

* feat : Http요청에 관한 응답 정보가 담긴 baseCode, SuccessCode, ErrorCode 생성(CC-114)

* feat : Http요청에 관한 응답 본문에 담을 객체 생성(CC-114)

* feat : 전역 예외 처리 및 핸들링 로직 생성
(CC-114)

* refactor : health check api에서 SuccessResponse를 사용하도록 수정
(CC-114)

* feat : RacingGame 도메인에서 발생하는 에러만을 처리하는 로직 생성
(CC-114)

* feat : racingGame 도메인 아키텍처 유지를 위한 .gitkeep 생성
(CC-114)

* feat : racingGame 도메인 아키텍처 유지를 위한 .gitkeep 생성
(CC-114)

* feat : 엔티티 createAt, updateAt 어노테이션 추가
(CC-114)

* refactor : @controller 대신 @RestController를 사용
(CC-114)

* format : 코드 포매팅 통일
(CC-114)

* test : 테스트코드 작성 연습을 위한 health check api 테스트 및 S3 통합테스트 코드 작성 (CC-111) (#13)

* test : 서버 health check 컨트롤러 테스트 코드 작성 (CC-111)

* test : 서버 health check 컨트롤러 테스트 코드 작성 (CC-111)

* test : 서버 health check 컨트롤러 테스트 코드 작성 (CC-111)

* feat : S3 컨트롤러에 responseEntity 설정 (CC-111)

* test : S3 통합테스트 환경 disabled (CC-111)

* docs : Pull Request template 업로드 (CC-111)

* rename : S3 controller 디렉터리 수정
(CC-111)

* refactor : health check api에서 SuccessResponse를 사용하도록 수정
(CC-114)

* refactor : @controller 대신 @RestController를 사용
(CC-114)

* format : 코드 포매팅 통일
(CC-114)

* fix : S3 컨트롤러에 존재하는 헬스체크 api 제거
(CC-114)
  • Loading branch information
j2noo authored Aug 5, 2024
1 parent be9e887 commit 576a082
Show file tree
Hide file tree
Showing 21 changed files with 247 additions and 35 deletions.
6 changes: 3 additions & 3 deletions src/main/java/ai/softeer/caecae/CaecaeApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
@SpringBootApplication
public class CaecaeApplication {

public static void main(String[] args) {
SpringApplication.run(CaecaeApplication.class, args);
}
public static void main(String[] args) {
SpringApplication.run(CaecaeApplication.class, args);
}

}
11 changes: 5 additions & 6 deletions src/main/java/ai/softeer/caecae/admin/api/S3Controller.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package ai.softeer.caecae.admin.api;
package ai.softeer.caecae;

import ai.softeer.caecae.global.dto.response.SuccessResponse;
import ai.softeer.caecae.global.utils.S3Service;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -14,11 +12,12 @@
public class S3Controller {
private final S3Service s3Service;

//TODO : admin 도메인의 정답 정보 등록 컨트롤러로 종속시키기
@PostMapping("/api/s3")
public ResponseEntity<SuccessResponse<String>> upload(@RequestParam("file") MultipartFile file) {
public String upload(@RequestParam("file") MultipartFile file) {
String filePath = s3Service.uploadFile(file);
return ResponseEntity.ok(new SuccessResponse<>(filePath));
return filePath + "created!";
//TODO : ResponseEntity 생성하기

}

}
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
package ai.softeer.caecae.global.controller;

import ai.softeer.caecae.global.dto.response.SuccessResponse;
import ai.softeer.caecae.global.enums.SuccessCode;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
@RequestMapping("/api/health")
@RestController
public class HealthTestController {
@GetMapping("")
@GetMapping("/api/health")
public ResponseEntity<SuccessResponse<String>> healthTest() {
return ResponseEntity.ok(new SuccessResponse<>(1000,"api health test에 성공했습니다.","health test v1"));
return SuccessResponse.of(SuccessCode.OK, "Caecae Spring Server Health Test ~!");
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
import lombok.AllArgsConstructor;
import lombok.Getter;

/**
* Http 요청에 대한 응답(성공,실패)시 본문에 반환할 객체
*/
@Getter
@AllArgsConstructor
public abstract class BaseResponse {
// 커스텀 응답 코드 종류
// TODO : 커스텀 응답코드 문서화
private int responseCode;
// 응답 정보를 담은 메시지
private String message;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
package ai.softeer.caecae.global.dto.response;

import ai.softeer.caecae.global.enums.ErrorCode;
import lombok.Getter;
import org.springframework.http.ResponseEntity;

/**
* Http 요청에 대한 실패 응답 본문에 반환할 객체
*/
@Getter
public class ErrorResponse extends BaseResponse{
public ErrorResponse(int responseCode, String message) {
super(responseCode, message);
public class ErrorResponse extends BaseResponse {

private ErrorResponse(ErrorCode errorCode) {
super(errorCode.getResponseCode(), errorCode.getMessage());
}

public static ResponseEntity<ErrorResponse> of(ErrorCode errorCode) {
return ResponseEntity.status(errorCode.getHttpStatus())
.body(new ErrorResponse(errorCode));
}

}
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
package ai.softeer.caecae.global.dto.response;

import lombok.Builder;
import ai.softeer.caecae.global.enums.SuccessCode;
import lombok.Getter;
import org.springframework.http.ResponseEntity;

/**
* Http 요청에 대한 성공 응답 본문에 반환할 객체
*/
@Getter
public class SuccessResponse<T> extends BaseResponse {
// httpResponse 를 통해 넘겨 줄 응답 데이터
private T data;
// 응답 성공 관련 정보

// 응답코드, 메세지, 반환 데이터를 파라미터로 받는 생성자
public SuccessResponse(int responseCode, String message, T data) {
super(responseCode, message);
// 성공 관련 정보, 반환 데이터를 파라미터로 받는 생성자
private SuccessResponse(SuccessCode successCode, T data) {
super(successCode.getResponseCode(), successCode.getMessage());
this.data = data;
}

// 코드 및 메시지를 설정하지 않은 생성자
public SuccessResponse(T data) {
super(0, "요청 성공 기본 메시지 입니다.");
this.data = data;

// 팩토리 메서드 부분
// Controller 에서 사용할 ResponseEntity 를 반환하는 팩토리메서드
public static <T> ResponseEntity<SuccessResponse<T>> of(SuccessCode successCode, T data) {
return ResponseEntity.status(successCode.getHttpStatus())
.body(new SuccessResponse<>(successCode, data));
}


}
14 changes: 13 additions & 1 deletion src/main/java/ai/softeer/caecae/global/entity/BaseEntity.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
package ai.softeer.caecae.global.entity;

import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

//TODO : JPA 의존성 설정 후 Audit, CreatedAt 등 어노테이션 설정
@Getter
@MappedSuperclass // 상속받은 엔티티가 아래 컬럼을 인식할 수 있음
@EntityListeners(AuditingEntityListener.class) // 자동으로 컬럼에 해당 값을 넣어주는 audit 기능
public abstract class BaseEntity {
// 엔티티가 생성된 시간
@CreatedDate
private LocalDateTime createdAt;

// 엔티티가 업데이트된 시간
@LastModifiedDate
private LocalDateTime updatedAt;
}
20 changes: 20 additions & 0 deletions src/main/java/ai/softeer/caecae/global/enums/BaseCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ai.softeer.caecae.global.enums;

import org.springframework.http.HttpStatus;

/**
* Http 요청에 대한 응답과 관련있는 정보
*/
public interface BaseCode {
// 커스텀 응답 코드 종류
int getResponseCode();
// 응답 정보를 담은 메시지
String getMessage();
// HttpStatus
HttpStatus getHttpStatus();


}



35 changes: 35 additions & 0 deletions src/main/java/ai/softeer/caecae/global/enums/ErrorCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package ai.softeer.caecae.global.enums;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

/**
* Http 요청에 대한 에러 응답과 관련있는 정보
*/
@Getter
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public enum ErrorCode implements BaseCode {
//TODO : 코드 문서화
/**
* 1000 : 틀린그림찾기
*/
NOT_FOUND(1000, "잘못된 요청입니다.", HttpStatus.NOT_FOUND),

/**
* 2xxx : 레이싱게임 ..
*/
NEED_AUTHENICATE(1000, "권한이 필요한 요청입니다,", HttpStatus.UNAUTHORIZED),


/**
* 9xxx : 기타 에러
*/
INTERNAL_SERVER_ERROR(-1, "서버 내부 오류입니다.", HttpStatus.INTERNAL_SERVER_ERROR);

private final int responseCode;
private final String message;
private final HttpStatus httpStatus;

}
32 changes: 32 additions & 0 deletions src/main/java/ai/softeer/caecae/global/enums/SuccessCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package ai.softeer.caecae.global.enums;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

/**
* Http 요청에 대한 성공 응답과 관련있는 정보
*/
@Getter
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public enum SuccessCode implements BaseCode {
//TODO : 코드 문서화
/**
* 1000 : 틀린그림찾기
*/
OK(1000, "요청이 성공했습니다.", HttpStatus.OK),

/**
* 2xxx : 레이싱게임 ..
*/
CREATED(1001, "생성 요청이 성공했습니다.", HttpStatus.CREATED),
USER_CREATED(1001, "유저 회원가입이 성공했습니다.", HttpStatus.CREATED),
TEAM_CREATED(1001, "팀 등록에 성공했습니다.", HttpStatus.CREATED);

private final int responseCode;
private final String message;
private final HttpStatus httpStatus;


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package ai.softeer.caecae.global.exception;

import ai.softeer.caecae.global.enums.ErrorCode;
import lombok.Getter;

@Getter
public class GlobalException extends RuntimeException {
private final ErrorCode errorCode;

public GlobalException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;


}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package ai.softeer.caecae.global.exception;

import ai.softeer.caecae.global.dto.response.ErrorResponse;
import ai.softeer.caecae.global.enums.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;

/**
* 전역 에러를 핸들링하여 HttpResponse 를 반환하는 핸들러
*/
@Slf4j
public class GlobalExceptionHandler {
// GlobalException 에 대한 에러 핸들링
@ExceptionHandler(value = GlobalException.class)
public ResponseEntity<ErrorResponse> handleGlobalException(GlobalException globalException) {
log.error(globalException.getMessage(), globalException);
return ErrorResponse.of(globalException.getErrorCode());
}

// 그 외 발생한 에러 핸들링
@ExceptionHandler(value = Exception.class)
public ResponseEntity<ErrorResponse> handleGlobalException(Exception exception) {
log.error(exception.getMessage(), exception);
return ErrorResponse.of(ErrorCode.INTERNAL_SERVER_ERROR);
}
}
10 changes: 5 additions & 5 deletions src/main/java/ai/softeer/caecae/global/utils/S3Service.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package ai.softeer.caecae.global.utils;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import lombok.RequiredArgsConstructor;
Expand All @@ -10,9 +9,9 @@
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException; // 추가
import java.io.InputStream; // 추가
import java.util.UUID; // 추가
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

@Slf4j
@Service
Expand All @@ -26,6 +25,7 @@ public class S3Service {

/**
* S3에 파일을 업로드 하는 서비스 로직
*
* @param file
* @return 파일 이름
*/
Expand All @@ -40,7 +40,7 @@ public String uploadFile(MultipartFile file) {
try (InputStream inputStream = file.getInputStream()) {
amazonS3.putObject(new PutObjectRequest(bucket, fileName, inputStream, objectMetadata));
// 올린 오브젝트에 대한 s3 url
filePath = amazonS3.getUrl(bucket, fileName).toString();
filePath = amazonS3.getUrl(bucket, fileName).toString();
} catch (IOException e) {
throw new IllegalArgumentException("파일이 없습니다.");
//TODO : 커스텀 에러 관리하기
Expand Down
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ public class RacingGameWinner extends BaseEntity {
private User user;

@Column(nullable = false)
private int rank;
private int ranking;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package ai.softeer.caecae.racinggame.domain.exception;

import ai.softeer.caecae.global.enums.ErrorCode;
import lombok.Getter;

@Getter
public class RacingGameException extends RuntimeException {
private final ErrorCode errorCode;

public RacingGameException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;


}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ai.softeer.caecae.racinggame.domain.exception;

import ai.softeer.caecae.global.dto.response.ErrorResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;

/**
* RacingGame 도메인에서 에러를 핸들링하여 HttpResponse 를 반환하는 핸들러
*/
@Slf4j
public class RacingGameExceptionHandler {
// RacingGameException 에 대한 에러 핸들링
@ExceptionHandler(value = RacingGameException.class)
public ResponseEntity<ErrorResponse> handleRacingGameException(RacingGameException globalException) {
log.error(globalException.getMessage(), globalException);
return ErrorResponse.of(globalException.getErrorCode());
}
}
Empty file.
Empty file.
2 changes: 1 addition & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ spring:

jpa:
hibernate:
ddl-auto: create
ddl-auto: update
properties:
hibernate:
show_sql: true
Expand Down
Loading

0 comments on commit 576a082

Please sign in to comment.