Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into feature/3_Hyeon-Uk_구매…
Browse files Browse the repository at this point in the history
…자_페이먼트_충전
  • Loading branch information
Hyeon-Uk committed Aug 12, 2024
2 parents 30c80ab + 993a90c commit 7e4a8aa
Show file tree
Hide file tree
Showing 17 changed files with 263 additions and 5 deletions.
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/bug-report.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
name: Report bug
about: 오류가 발생한 영역에 대해 보고합니다 [Dev]
title: "[BUG] "
labels: bug
title: "[오류] "
labels: 🐞 BugFix
assignees: ''

---
Expand Down
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/feature-request.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
name: Feature request
about: Github Discussion, 회의에서 화제가 된 주제에 대해 제안합니다 [Moderator, Chef]
title: '[REQ]'
labels: enhancement
title: "[기능] "
labels: ✨ Feature
assignees: ''

---
Expand Down
3 changes: 2 additions & 1 deletion .github/pr-template.md → .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
## 💡 다음 이슈를 해결했어요.

### Issue Link - #1

- (가능한 한 자세히 작성해 주시면 도움이 됩니다.)

<br>

## 💡 이슈를 처리하면서 추가된 코드가 있어요.
### Issue Link - #1

- (없다면 이 문항을 지워주세요.)

Expand Down
21 changes: 21 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Build-Test

on:
pull_request:
branches: [ main ]

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Build with Gradle
run: ./gradlew build
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package camp.woowak.lab.common.advice;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.AliasFor;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RestControllerAdvice
@Order(Ordered.LOWEST_PRECEDENCE - 1)
public @interface DomainExceptionHandler {
@AliasFor(annotation = RestControllerAdvice.class, attribute = "basePackages")
String[] basePackages() default {};

@AliasFor(annotation = RestControllerAdvice.class, attribute = "basePackageClasses")
Class<?>[] basePackageClasses() default {};

@AliasFor(annotation = RestControllerAdvice.class, attribute = "assignableTypes")
Class<?>[] assignableTypes() default {};

@AliasFor(annotation = RestControllerAdvice.class, attribute = "annotations")
Class<? extends Annotation>[] annotations() default {};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package camp.woowak.lab.common.advice;

import org.springframework.http.HttpStatus;
import org.springframework.http.ProblemDetail;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(Exception.class)
public ResponseEntity<ProblemDetail> handleAllUncaughtException(Exception e) {
ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.INTERNAL_SERVER_ERROR,
e.getMessage());
problemDetail.setProperty("errorCode", "9999");

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(problemDetail);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package camp.woowak.lab.common.exception;

public class BadRequestException extends HttpStatusException {
public BadRequestException(ErrorCode errorCode) {
super(errorCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package camp.woowak.lab.common.exception;

public class ConflictException extends HttpStatusException {
public ConflictException(ErrorCode errorCode) {
super(errorCode);
}
}
7 changes: 7 additions & 0 deletions src/main/java/camp/woowak/lab/common/exception/ErrorCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package camp.woowak.lab.common.exception;

public interface ErrorCode {
int getStatus();
String getErrorCode();
String getMessage();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package camp.woowak.lab.common.exception;

public class ForbiddenException extends HttpStatusException {
public ForbiddenException(ErrorCode errorCode) {
super(errorCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package camp.woowak.lab.common.exception;

public class HttpStatusException extends RuntimeException {
private final ErrorCode errorCode;

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

public ErrorCode errorCode() {
return errorCode;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package camp.woowak.lab.common.exception;

public class MethodNotAllowedException extends HttpStatusException {
public MethodNotAllowedException(ErrorCode errorCode) {
super(errorCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package camp.woowak.lab.common.exception;

public class NotFoundException extends HttpStatusException {
public NotFoundException(ErrorCode errorCode) {
super(errorCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package camp.woowak.lab.common.exception;

public class UnauthorizedException extends HttpStatusException {
public UnauthorizedException(ErrorCode errorCode) {
super(errorCode);
}
}
25 changes: 25 additions & 0 deletions src/main/java/camp/woowak/lab/web/api/utils/APIResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package camp.woowak.lab.web.api.utils;

import org.springframework.http.HttpStatus;

/**
* APIResponse를 Jackson의 ObjectMapper와 함께 사용하려면,
* Generic Type의 {@code data}에는 Getter 메서드가 필요합니다.
*/
public class APIResponse<T> {
private final T data;
private final int status;

APIResponse(final HttpStatus status, final T data) {
this.data = data;
this.status = status.value();
}

public T getData() {
return data;
}

public int getStatus() {
return status;
}
}
19 changes: 19 additions & 0 deletions src/main/java/camp/woowak/lab/web/api/utils/APIUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package camp.woowak.lab.web.api.utils;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

/**
*
* API Utils
* of Method는 status와 data를 이용해 APIResponse객체를 만들 수 있습니다.
*
*/
public final class APIUtils {
private APIUtils() {
}

public static <T> ResponseEntity<APIResponse<T>> of(HttpStatus status, T data) {
return new ResponseEntity<>(new APIResponse<>(status, data), status);
}
}
73 changes: 73 additions & 0 deletions src/test/java/camp/woowak/lab/web/api/utils/APIUtilsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package camp.woowak.lab.web.api.utils;

import static org.assertj.core.api.Assertions.*;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import com.fasterxml.jackson.core.JsonProcessingException;

@DisplayName("APIUtils 클래스")
class APIUtilsTest {
@Nested
@DisplayName("of메서드의")
class OfTest {
@Nested
@DisplayName("HttpStatus 값과 Data를 파라미터로 받는 메서드는")
class ParamWithHttpStatusAndData {
@Test
@DisplayName("data와 status를 가지는 APIResponse를 생성할 수 있다.")
void APIResponseWithHttpStatusAndData() throws JsonProcessingException {
//given
HttpStatus status = HttpStatus.OK;
String message = "hello world";

//when
ResponseEntity<APIResponse<String>> apiResponse = APIUtils.of(status, message);

//then
assertThat(apiResponse.getStatusCode()).isEqualTo(status);
assertThat(apiResponse.getBody().getData()).isEqualTo(message);
assertThat(apiResponse.getBody().getStatus()).isEqualTo(status.value());
}

@Test
@DisplayName("data가 객체인 경우도 APIResponse를 생성할 수 있다.")
void APIResponseWithObjectData() throws JsonProcessingException {
//given
HttpStatus status = HttpStatus.OK;
Example example = new Example(27, "Hyeon-Uk");

//when
ResponseEntity<APIResponse<Example>> apiResponse = APIUtils.of(status, example);

//then
assertThat(apiResponse.getStatusCode()).isEqualTo(status);
assertThat(apiResponse.getBody().getData()).isEqualTo(example);
assertThat(apiResponse.getBody().getStatus()).isEqualTo(status.value());
}

private class Example {
int age;
String name;

public Example(int age, String name) {
this.age = age;
this.name = name;
}

public int getAge() {
return age;
}

public String getName() {
return name;
}
}
}

}
}

0 comments on commit 7e4a8aa

Please sign in to comment.