Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create apiPayLoad and baseEntity #2

Merged
merged 4 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ dependencies {
implementation 'io.springfox:springfox-swagger-ui:2.9.2'
//aws
implementation group: 'io.awspring.cloud', name: 'spring-cloud-starter-aws', version: '2.4.4'
implementation 'org.springframework.boot:spring-boot-starter-validation'

}
jar {
Expand Down
36 changes: 36 additions & 0 deletions src/main/java/umc/beanstalk/common/apiPayload/ApiResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package umc.beanstalk.common.apiPayload;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.AllArgsConstructor;
import lombok.Getter;
import umc.beanstalk.common.apiPayload.code.BaseCode;
import umc.beanstalk.common.apiPayload.code.status.SuccessStatus;

@Getter
@AllArgsConstructor
@JsonPropertyOrder({"isSuccess","code","message","result"})
public class ApiResult<T> {
@JsonProperty("isSuccess")
private final Boolean isSuccess;
private final String code;
private final String message;
@JsonInclude(JsonInclude.Include.NON_NULL)
private T result;

// 실패한 경우 응답 생성
public static <T> ApiResult<T> onFailure(String code, String message, T data){
return new ApiResult<>(true, code, message, data);
}

//성공한 경우 응답 생성
public static <T> ApiResult<T> onSuccess(T result){
return new ApiResult<>(true, SuccessStatus._OK.getCode() , SuccessStatus._OK.getMessage(), result);
}

public static <T> ApiResult<T> of(BaseCode code, T result){
return new ApiResult<>(true, code.getReasonHttpStatus().getCode(), code.getReasonHttpStatus().getMessage(), result);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package umc.beanstalk.common.apiPayload.code;

public interface BaseCode {
public ReasonDTO getReason();

public ReasonDTO getReasonHttpStatus();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package umc.beanstalk.common.apiPayload.code;

public interface BaseErrorCode {
public ErrorReasonDTO getReason();
public ErrorReasonDTO getReasonHttpStatus();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package umc.beanstalk.common.apiPayload.code;

import lombok.Builder;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@Builder
public class ErrorReasonDTO {
private HttpStatus httpStatus;

private final Boolean isSuccess;
private final String code;
private final String message;

public boolean getIsSuccess(){return isSuccess;}
}
17 changes: 17 additions & 0 deletions src/main/java/umc/beanstalk/common/apiPayload/code/ReasonDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package umc.beanstalk.common.apiPayload.code;

import lombok.Builder;
import lombok.Getter;
import org.springframework.http.HttpStatus;
@Getter

@Builder
public class ReasonDTO {
private HttpStatus httpStatus;

private final boolean isSuccess;
private final String code;
private final String message;

public boolean getIsSuccess(){return isSuccess;}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package umc.beanstalk.common.apiPayload.code.status;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import umc.beanstalk.common.apiPayload.code.BaseErrorCode;
import umc.beanstalk.common.apiPayload.code.ErrorReasonDTO;

@Getter
@AllArgsConstructor
public enum ErrorStatus implements BaseErrorCode {
// 가장 일반적인 응답
_INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR,"COMMON500","서버 에러, 관리자에게 문의 바랍니다."),
_BAD_REQUEST(HttpStatus.BAD_REQUEST,"COMMON400","잘못된 요청입니다."),
_UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"COMMON401","인증이 필요합니다."),
_FORBIDDEN(HttpStatus.FORBIDDEN, "COMMON403", "금지된 요청입니다."),
// 멤버 관련 응답
MEMBER_NOT_FOUND(HttpStatus.BAD_REQUEST,"MEMBER4001","사용자가 없습니다."),
NICKNAME_NOT_EXIST(HttpStatus.BAD_REQUEST,"MEMBER4002", "닉네임은 필수 입니다."),
// 멤버 선호 음식
FOOD_CATEGORY_NOT_FOUND(HttpStatus.BAD_REQUEST,"PREFER4001","음식 카테고리가 없습니다."),
// 유저 미션
ACCEPT_MISSION_NOT_FOUND(HttpStatus.BAD_REQUEST,"USERMISSION4001","유저가 수락한 미션이 없습니다."),
//식당 관련 응답
STORE_NOT_FOUND(HttpStatus.BAD_REQUEST,"STORER4002","식당명은 필수 입니다."),
STORE_NOT_EXIST(HttpStatus.BAD_REQUEST,"STORE4001", "식당이 없습니다."),
// 지역 관련 응답
REGION_NOT_FOUND(HttpStatus.BAD_REQUEST,"REGION4001","해당 지역이 없습니다."),
//미션 관련 응답
MISSION_NOT_EXIST(HttpStatus.BAD_REQUEST,"MISSION4001", "미션이 없습니다."),
Mission_Already_Accept(HttpStatus.BAD_REQUEST,"MISSION4002", "이미 수락한 미션입니다."),
MISSION_COMPLETE(HttpStatus.BAD_REQUEST,"MISSION4003", "이미 완료한 미션입니다."),
//페이지 관련
PAGE_NOT_FOUND(HttpStatus.BAD_REQUEST,"PAGE4001","해당 페이지가 없습니다."),
// 예시 ...
ARTICLE_NOT_FOUND(HttpStatus.NOT_FOUND, "ARTICLE4001", "게시글이 없습니다."),
TEMP_EXCEPTION(HttpStatus.BAD_REQUEST,"TEMP40001","이거는 테스트");

private final HttpStatus httpStatus;
private final String code;
private final String message;

@Override
public ErrorReasonDTO getReason(){
return ErrorReasonDTO.builder()
.message(message)
.code(code)
.isSuccess(false)
.build();
}
@Override
public ErrorReasonDTO getReasonHttpStatus() {
return ErrorReasonDTO.builder()
.message(message)
.code(code)
.isSuccess(false)
.httpStatus(httpStatus)
.build()
;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package umc.beanstalk.common.apiPayload.code.status;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import umc.beanstalk.common.apiPayload.code.BaseCode;
import umc.beanstalk.common.apiPayload.code.ReasonDTO;

@Getter
@AllArgsConstructor
public enum SuccessStatus implements BaseCode {
// 일반적인 응답
_OK(HttpStatus.OK, "COMMON200", "성공입니다.");

// 멤버 관련 응답

// ~~ 관련 응답
private final HttpStatus httpStatus;
private final String code;
private final String message;

@Override
public ReasonDTO getReason() {
return ReasonDTO.builder()
.message(message)
.code(code)
.isSuccess(true)
.build();
}

@Override
public ReasonDTO getReasonHttpStatus() {
return ReasonDTO.builder()
.message(message)
.code(code)
.isSuccess(true)
.httpStatus(httpStatus)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package umc.beanstalk.common.apiPayload.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import umc.beanstalk.common.apiPayload.ApiResult;
import umc.beanstalk.common.apiPayload.code.ErrorReasonDTO;
import umc.beanstalk.common.apiPayload.code.status.ErrorStatus;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@RestControllerAdvice(annotations = {RestController.class})
public class ExceptionAdvice extends ResponseEntityExceptionHandler {

@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<Object> handleConstraintViolationException(ConstraintViolationException e, WebRequest request) {
String errorMessage = e.getConstraintViolations().stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.joining("; "));

return handleExceptionInternalConstraint(e, ErrorStatus.valueOf(errorMessage), HttpHeaders.EMPTY, request);
}

@Override
public ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException e, HttpHeaders headers, HttpStatus status, WebRequest request) {

Map<String, String> errors = new LinkedHashMap<>();

e.getBindingResult().getFieldErrors().stream()
.forEach(fieldError -> {
String fieldName = fieldError.getField();
String errorMessage = Optional.ofNullable(fieldError.getDefaultMessage()).orElse("");
errors.merge(fieldName, errorMessage, (existingErrorMessage, newErrorMessage) -> existingErrorMessage + ", " + newErrorMessage);
});

return handleExceptionInternalArgs(e, HttpHeaders.EMPTY, ErrorStatus.valueOf("_BAD_REQUEST"), request, errors);
}

@ExceptionHandler
public ResponseEntity<Object> exception(Exception e, WebRequest request) {
e.printStackTrace();

return handleExceptionInternalFalse(e, ErrorStatus._INTERNAL_SERVER_ERROR, HttpHeaders.EMPTY, ErrorStatus._INTERNAL_SERVER_ERROR.getHttpStatus(), request, e.getMessage());
}

@ExceptionHandler(value = GeneralException.class)
public ResponseEntity onThrowException(GeneralException generalException, HttpServletRequest request) {
ErrorReasonDTO errorReasonHttpStatus = generalException.getErrorReasonHttpStatus();
return handleExceptionInternal(generalException, errorReasonHttpStatus, null, request);
}
/*
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<Object> handleConstraintViolationException(ConstraintViolationException ex) {
// 여기서 ConstraintViolationException에서 얻은 정보를 활용하여 적절한 응답을 생성
// ex.getMessage() 등을 활용하여 에러 메시지를 추출할 수 있음
String errorMessage = "Validation failed: " + ex.getMessage();
return new ResponseEntity<>(errorMessage, HttpStatus.BAD_REQUEST);
}

*/
private ResponseEntity<Object> handleExceptionInternal(Exception e, ErrorReasonDTO reason,
HttpHeaders headers, HttpServletRequest request) {

ApiResult<Object> body = ApiResult.onFailure(reason.getCode(), reason.getMessage(), null);
// e.printStackTrace();

WebRequest webRequest = new ServletWebRequest(request);
return super.handleExceptionInternal(
e,
body,
headers,
reason.getHttpStatus(),
webRequest
);
}

private ResponseEntity<Object> handleExceptionInternalFalse(Exception e, ErrorStatus errorCommonStatus,
HttpHeaders headers, HttpStatus status, WebRequest request, String errorPoint) {
ApiResult<Object> body = ApiResult.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), errorPoint);
return super.handleExceptionInternal(
e,
body,
headers,
status,
request
);
}

private ResponseEntity<Object> handleExceptionInternalArgs(Exception e, HttpHeaders headers, ErrorStatus errorCommonStatus,
WebRequest request, Map<String, String> errorArgs) {
ApiResult<Object> body = ApiResult.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), errorArgs);
return super.handleExceptionInternal(
e,
body,
headers,
errorCommonStatus.getHttpStatus(),
request
);
}

private ResponseEntity<Object> handleExceptionInternalConstraint(Exception e, ErrorStatus errorCommonStatus,
HttpHeaders headers, WebRequest request) {
ApiResult<Object> body = ApiResult.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), null);
return super.handleExceptionInternal(
e,
body,
headers,
errorCommonStatus.getHttpStatus(),
request
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package umc.beanstalk.common.apiPayload.exception;

import lombok.AllArgsConstructor;
import lombok.Getter;
import umc.beanstalk.common.apiPayload.code.BaseErrorCode;
import umc.beanstalk.common.apiPayload.code.ErrorReasonDTO;

@Getter
@AllArgsConstructor
public class GeneralException extends RuntimeException{
private BaseErrorCode code;
public ErrorReasonDTO getErrorReason(){
return this.code.getReason();
}
public ErrorReasonDTO getErrorReasonHttpStatus(){
return this.code.getReasonHttpStatus();
}
}
23 changes: 23 additions & 0 deletions src/main/java/umc/beanstalk/common/domain/BaseEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package umc.beanstalk.common.domain;

import lombok.Getter;
import lombok.Setter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@Getter
public class BaseEntity {
@CreatedDate
private LocalDateTime createdAt;

@Setter
@LastModifiedDate
private LocalDateTime updatedAt;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package umc.beanstalk.user_choice.data.domain;

import lombok.*;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class UserChoice {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
}
Loading