From 6d308349c57798af22633216c822de83490ea800 Mon Sep 17 00:00:00 2001 From: JoHyeonseok Date: Wed, 21 Sep 2022 01:37:15 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20ApiError,=20ApiResponse=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../gdscpknu/controller/ApiError.java | 36 ++++++++++++++++ .../gdscpknu/controller/ApiResponse.java | 42 +++++++++++++++++++ .../controller/GlobalExceptionHandler.java | 32 ++++++++++++++ 4 files changed, 111 insertions(+) create mode 100644 src/main/java/com/gdscpknu/gdscpknu/controller/ApiError.java create mode 100644 src/main/java/com/gdscpknu/gdscpknu/controller/ApiResponse.java create mode 100644 src/main/java/com/gdscpknu/gdscpknu/controller/GlobalExceptionHandler.java diff --git a/build.gradle b/build.gradle index 25b45d3..d0aa3c8 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.jraf:klibnotion:1.11.0' + implementation group: 'org.apache.commons', name: 'commons-lang3', version: "3.4" compileOnly 'org.projectlombok:lombok' runtimeOnly 'mysql:mysql-connector-java' annotationProcessor 'org.projectlombok:lombok' diff --git a/src/main/java/com/gdscpknu/gdscpknu/controller/ApiError.java b/src/main/java/com/gdscpknu/gdscpknu/controller/ApiError.java new file mode 100644 index 0000000..bbb0ded --- /dev/null +++ b/src/main/java/com/gdscpknu/gdscpknu/controller/ApiError.java @@ -0,0 +1,36 @@ +package com.gdscpknu.gdscpknu.controller; + +import lombok.Getter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.springframework.http.HttpStatus; + +@Getter +public class ApiError { + + private final String MESSAGE = "message"; + private final String STATUS = "status"; + private final String msg; + private final int status; + + public ApiError(String msg, int status) { + this.msg = msg; + this.status = status; + } + + public ApiError(String msg, HttpStatus status) { + this(msg, status.value()); + } + + public ApiError(Throwable throwable, HttpStatus status) { + this(throwable.getMessage(), status.value()); + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append(MESSAGE, msg) + .append(STATUS, status) + .toString(); + } +} \ No newline at end of file diff --git a/src/main/java/com/gdscpknu/gdscpknu/controller/ApiResponse.java b/src/main/java/com/gdscpknu/gdscpknu/controller/ApiResponse.java new file mode 100644 index 0000000..8345b20 --- /dev/null +++ b/src/main/java/com/gdscpknu/gdscpknu/controller/ApiResponse.java @@ -0,0 +1,42 @@ +package com.gdscpknu.gdscpknu.controller; + +import lombok.Getter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.springframework.http.HttpStatus; + +@Getter +public class ApiResponse { + + private final boolean success; + + private final T response; + + private final ApiError error; + + public ApiResponse(boolean success, T response, ApiError error) { + this.success = success; + this.response = response; + this.error = error; + } + + public static ApiResponse SUCCESS(T response){ + return new ApiResponse<>(true, response, null); + } + + public static ApiResponse ERROR(String msg, HttpStatus status){ + return new ApiResponse<>(false, null, new ApiError(msg, status)); + } + + public static ApiResponse ERROR(Throwable throwable, HttpStatus status){ + return new ApiResponse<>(false, null, new ApiError(throwable, status)); + } + + public String toString() { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("success", success) + .append("response", response) + .append("error", error) + .toString(); + } +} \ No newline at end of file diff --git a/src/main/java/com/gdscpknu/gdscpknu/controller/GlobalExceptionHandler.java b/src/main/java/com/gdscpknu/gdscpknu/controller/GlobalExceptionHandler.java new file mode 100644 index 0000000..ed89c8b --- /dev/null +++ b/src/main/java/com/gdscpknu/gdscpknu/controller/GlobalExceptionHandler.java @@ -0,0 +1,32 @@ +package com.gdscpknu.gdscpknu.controller; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import static com.gdscpknu.gdscpknu.controller.ApiResponse.ERROR; + + +@ControllerAdvice +public class GlobalExceptionHandler { + + private final Logger log = LoggerFactory.getLogger(getClass()); + + private ResponseEntity> newResponse(Throwable throwable, HttpStatus status) { + HttpHeaders headers = new HttpHeaders(); + headers.add("Content-Type", "application/json"); + return new ResponseEntity<>(ERROR(throwable, status), headers, status); + } + + @ExceptionHandler({ + IllegalArgumentException.class, + }) + public ResponseEntity handleBadRequestException(Exception e) { + log.debug("Bad request exception occurred: {}", e.getMessage(), e); + return newResponse(e, HttpStatus.BAD_REQUEST); + } + +} \ No newline at end of file From b32591249ecd3242e8f2a852a805e38f92813119 Mon Sep 17 00:00:00 2001 From: JoHyeonseok Date: Wed, 21 Sep 2022 11:37:23 +0900 Subject: [PATCH 2/4] =?UTF-8?q?test:=20=EC=8B=A4=EC=A0=9C=20notion=20DB?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95=20-=20given=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20-=20"=EC=97=AD=ED=95=A0"=EB=A1=9C=20sort=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=20-=20plainTestList=20=3D>=20names,=20roles,?= =?UTF-8?q?=20emails=EB=A1=9C=20=EB=B6=84=ED=95=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gdscpknu/notion/NotionApiTest.java | 43 +++++++++++-------- .../gdscpknu/gdscpknu/notion/NotionTable.java | 4 +- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/test/java/com/gdscpknu/gdscpknu/notion/NotionApiTest.java b/src/test/java/com/gdscpknu/gdscpknu/notion/NotionApiTest.java index cb8e5f7..a8809ce 100644 --- a/src/test/java/com/gdscpknu/gdscpknu/notion/NotionApiTest.java +++ b/src/test/java/com/gdscpknu/gdscpknu/notion/NotionApiTest.java @@ -8,6 +8,7 @@ import org.jraf.klibnotion.model.page.Page; import org.jraf.klibnotion.model.pagination.Pagination; import org.jraf.klibnotion.model.pagination.ResultPage; +import org.jraf.klibnotion.model.property.sort.PropertySort; import org.junit.jupiter.api.Test; import java.util.ArrayList; @@ -36,7 +37,6 @@ public void getTable() { ); //then -// System.out.println("simpleQueryResultPage = " + simpleQueryResultPage.results); assertThat(database.getTitle().getPlainText()).isEqualTo(notionTable.getTableName()); assertThat(simpleQueryResultPage.results.size()).isEqualTo(notionTable.getMemberNum()); } @@ -44,9 +44,9 @@ public void getTable() { @Test public void getRowByEmail() { //given - String name = "가나다"; - String role = "Core"; - String email = "ganada@pukyong.ac.kr"; + String name = "남우진"; + String role = "Lead"; + String email = "mokujin94@gmail.com"; //when ResultPage simpleQueryResultPage = client.getDatabases().queryDatabase( @@ -73,14 +73,16 @@ public void getRowByEmail() { @Test void getPlainTexts() { //given - String name = "가나다"; - String role = "Core"; - String email = "ganada@pukyong.ac.kr"; + String name = "남우진"; + String role = "Lead"; + String email = "mokujin94@gmail.com"; + + // "역할" 기준으로 정렬 ResultPage simpleQueryResultPage = client.getDatabases().queryDatabase( notionTable.getDATABASE_ID(), null, - null, + new PropertySort().ascending("역할"), new Pagination() ); @@ -89,7 +91,9 @@ void getPlainTexts() { * KlibNotion 라이브러리에서 name, email, role 값을 정규식으로 추출하였음 */ String resultInString = simpleQueryResultPage.results.toString(); - List plainTextList = new ArrayList<>(); + List names = new ArrayList<>(); + List roles = new ArrayList<>(); + List emails = new ArrayList<>(); // 문자열 중 "(plainText=" ~ "," 범위(이름, 이메일) OR " "name=" ~ "," 범위(역할) 문자열을 추출 Pattern namePattern = Pattern.compile("(?<=\\(plainText=)(.*?)(?=,)"); Pattern emailPattern = Pattern.compile("(?<=\\bname=이메일, value=)(.*?)(?=\\))"); @@ -98,20 +102,23 @@ void getPlainTexts() { Matcher emailMatcher = emailPattern.matcher(resultInString); Matcher roleMatcher = rolePattern.matcher(resultInString); while (nameMatcher.find()) { - plainTextList.add(nameMatcher.group()); - } - while (emailMatcher.find()) { - plainTextList.add(emailMatcher.group()); + names.add(nameMatcher.group()); } while (roleMatcher.find()) { - plainTextList.add(roleMatcher.group()); + roles.add(roleMatcher.group()); } + while (emailMatcher.find()) { + emails.add(emailMatcher.group()); + } + //then - assertThat(plainTextList.size()).isEqualTo(notionTable.getMemberNum() * 3); - assertThat(plainTextList.get(0)).isEqualTo(name); - assertThat(plainTextList.get(3)).isEqualTo(email); - assertThat(plainTextList.get(6)).isEqualTo(role); + assertThat(names.size()).isEqualTo(notionTable.getMemberNum()); + assertThat(roles.size()).isEqualTo(notionTable.getMemberNum()); + assertThat(emails.size()).isEqualTo(notionTable.getMemberNum()); + assertThat(names.get(0)).isEqualTo(name); + assertThat(roles.get(0)).isEqualTo(role); + assertThat(emails.get(0)).isEqualTo(email); } } \ No newline at end of file diff --git a/src/test/java/com/gdscpknu/gdscpknu/notion/NotionTable.java b/src/test/java/com/gdscpknu/gdscpknu/notion/NotionTable.java index 7f1480c..5a21dd8 100644 --- a/src/test/java/com/gdscpknu/gdscpknu/notion/NotionTable.java +++ b/src/test/java/com/gdscpknu/gdscpknu/notion/NotionTable.java @@ -8,8 +8,8 @@ public class NotionTable { private final String TOKEN = ""; private final String DATABASE_ID = ""; - private final String tableName = "MEMBER PROFILE"; - private final int memberNum = 3; + private final String tableName = "멤버 소개"; + private final int memberNum = 39; public BlockingNotionClient initClient() { NotionClient notionClient = NotionClient.newInstance( From 2a0ddc5a50cc4de38cbe0cc13ed654b67557e538 Mon Sep 17 00:00:00 2001 From: JoHyeonseok Date: Thu, 22 Sep 2022 03:22:42 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20#6=20MemberController.java=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gdscpknu/GdscpknuApplication.java | 4 ++- .../gdscpknu/controller/MemberController.java | 27 +++++++++++++++++++ .../gdscpknu/gdscpknu/notion/GdscNotion.java | 13 ++------- .../gdscpknu/service/MemberService.java | 2 +- 4 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/gdscpknu/gdscpknu/controller/MemberController.java diff --git a/src/main/java/com/gdscpknu/gdscpknu/GdscpknuApplication.java b/src/main/java/com/gdscpknu/gdscpknu/GdscpknuApplication.java index a9b33f9..dc9a0f7 100644 --- a/src/main/java/com/gdscpknu/gdscpknu/GdscpknuApplication.java +++ b/src/main/java/com/gdscpknu/gdscpknu/GdscpknuApplication.java @@ -2,8 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -@SpringBootApplication +// DB 연결 없이 실행하기 위해 DataSourceAutoConfiguration 제외 +@SpringBootApplication(exclude={DataSourceAutoConfiguration.class}) public class GdscpknuApplication { public static void main(String[] args) { diff --git a/src/main/java/com/gdscpknu/gdscpknu/controller/MemberController.java b/src/main/java/com/gdscpknu/gdscpknu/controller/MemberController.java new file mode 100644 index 0000000..abeacd7 --- /dev/null +++ b/src/main/java/com/gdscpknu/gdscpknu/controller/MemberController.java @@ -0,0 +1,27 @@ +package com.gdscpknu.gdscpknu.controller; + +import com.gdscpknu.gdscpknu.domain.Member; +import com.gdscpknu.gdscpknu.service.MemberService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import java.util.List; + +@RestController +@RequestMapping("/member") +public class MemberController { + + private final MemberService memberService; + + @Autowired + public MemberController(MemberService memberService) { + this.memberService = memberService; + } + + + @GetMapping + public ApiResponse> getProfiles() { + return ApiResponse.SUCCESS(memberService.getAllMember()); + } +} diff --git a/src/main/java/com/gdscpknu/gdscpknu/notion/GdscNotion.java b/src/main/java/com/gdscpknu/gdscpknu/notion/GdscNotion.java index 226aaba..0a12845 100644 --- a/src/main/java/com/gdscpknu/gdscpknu/notion/GdscNotion.java +++ b/src/main/java/com/gdscpknu/gdscpknu/notion/GdscNotion.java @@ -11,15 +11,10 @@ @Component public class GdscNotion { - @Value("${testNotion.introduce.token}") + @Value("${gdscNotion.introduce.token}") private String TOKEN; - @Value("${testNotion.introduce.databaseId}") + @Value("${gdscNotion.introduce.databaseId}") private String DATABASE_ID; - private final BlockingNotionClient client; - - public GdscNotion(BlockingNotionClient client) { - this.client = initClient(); - } public BlockingNotionClient initClient() { NotionClient notionClient = NotionClient.newInstance( @@ -30,10 +25,6 @@ public BlockingNotionClient initClient() { return BlockingNotionClientUtils.asBlockingNotionClient(notionClient); } - public BlockingNotionClient getClient() { - return client; - } - public String getTOKEN() { return TOKEN; } diff --git a/src/main/java/com/gdscpknu/gdscpknu/service/MemberService.java b/src/main/java/com/gdscpknu/gdscpknu/service/MemberService.java index a84ce61..d14c439 100644 --- a/src/main/java/com/gdscpknu/gdscpknu/service/MemberService.java +++ b/src/main/java/com/gdscpknu/gdscpknu/service/MemberService.java @@ -28,7 +28,7 @@ public class MemberService { @Autowired public MemberService(GdscNotion gdscNotion) { this.gdscNotion = gdscNotion; - client = gdscNotion.getClient(); + client = gdscNotion.initClient(); } public List getAllMember() { From 0745d841df96b6d4a40405a18affb385ea678d5f Mon Sep 17 00:00:00 2001 From: JoHyeonseok Date: Thu, 22 Sep 2022 03:42:36 +0900 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20#6=20sortMembers()=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80=20-=20members=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EB=A5=BC=20Lead,=20Core=20Member,=20Member,=20Senior?= =?UTF-8?q?=20=EC=88=9C=EC=9C=BC=EB=A1=9C=20=EC=A0=95=EB=A0=AC=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=ED=95=A8=EC=88=98=20=EC=B6=94=EA=B0=80=20-=20?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=B8=94=20=EC=88=9C=EC=84=9C=EC=97=90?= =?UTF-8?q?=EB=94=B0=EB=9D=BC=20member=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EB=B3=80=EC=88=98=EB=A5=BC=20name,=20role,=20email=20=EC=88=9C?= =?UTF-8?q?=EC=84=9C=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/gdscpknu/gdscpknu/domain/Member.java | 7 ++-- .../gdscpknu/service/MemberService.java | 35 +++++++++++++++++-- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/gdscpknu/gdscpknu/domain/Member.java b/src/main/java/com/gdscpknu/gdscpknu/domain/Member.java index 895b964..3951b49 100644 --- a/src/main/java/com/gdscpknu/gdscpknu/domain/Member.java +++ b/src/main/java/com/gdscpknu/gdscpknu/domain/Member.java @@ -6,13 +6,12 @@ @Getter public class Member { private String name; - private String email; private String role; - + private String email; @Builder - public Member(String name, String email, String role) { + public Member(String name, String role, String email) { this.name = name; - this.email = email; this.role = role; + this.email = email; } } diff --git a/src/main/java/com/gdscpknu/gdscpknu/service/MemberService.java b/src/main/java/com/gdscpknu/gdscpknu/service/MemberService.java index d14c439..1532112 100644 --- a/src/main/java/com/gdscpknu/gdscpknu/service/MemberService.java +++ b/src/main/java/com/gdscpknu/gdscpknu/service/MemberService.java @@ -46,11 +46,13 @@ public List getAllMember() { extractName(resultInString); extractEmail(resultInString); extractRole(resultInString); - addMember(); + addMembers(); + sortMembers(); return members; } + private void getMemberIntroPage() { memberIntroPage = client.getDatabases().queryDatabase( gdscNotion.getDATABASE_ID(), @@ -84,14 +86,41 @@ private void extractRole(String resultInString) { } } - private void addMember() { + private void addMembers() { for (int i = 0; i < nameList.size(); i++) { Member member = Member.builder() .name(nameList.get(i)) - .email(emailList.get(i)) .role(roleList.get(i)) + .email(emailList.get(i)) .build(); members.add(member); } } + + private void sortMembers() { +// members를 Lead, Core Member, Member, Senior 순으로 정렬 + members.sort((o1, o2) -> { + if (o1.getRole().equals("Lead")) { + return -1; + } else if (o2.getRole().equals("Lead")) { + return 1; + } else if (o1.getRole().equals("Core Member")) { + return -1; + } else if (o2.getRole().equals("Core Member")) { + return 1; + } else if (o1.getRole().equals("Member")) { + return -1; + } else if (o2.getRole().equals("Member")) { + return 1; + } else if (o1.getRole().equals("Senior")) { + return -1; + } else if (o2.getRole().equals("Senior")) { + return 1; + } else { + return 0; + } + }); + + } + }