From b0630897e5d7d93d280d21805f5b396449b2a336 Mon Sep 17 00:00:00 2001 From: Hyeonggon Yoo <42.hyeyoo@gmail.com> Date: Fri, 3 May 2024 16:25:56 +0900 Subject: [PATCH 1/4] =?UTF-8?q?GET,=20PUT,=20DELETE=20/posts/{postId}=2040?= =?UTF-8?q?4=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PUT, DELETE, GET에 대하여 존재하지 않는 포스트에 대한 작업은 404를 리턴하도록 수정 Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com> --- .../controller/PostController.java | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/com/cnu/devlog_springboot/controller/PostController.java b/src/main/java/com/com/cnu/devlog_springboot/controller/PostController.java index 7d6847f..5b8284b 100644 --- a/src/main/java/com/com/cnu/devlog_springboot/controller/PostController.java +++ b/src/main/java/com/com/cnu/devlog_springboot/controller/PostController.java @@ -24,7 +24,12 @@ public ResponseEntity> getPosts() { // GET /posts/{postId} @GetMapping("{postId}") public ResponseEntity getPost(@PathVariable("postId")Integer postId) { - return ResponseEntity.ok(postService.getPost(postId)); + Post post = postService.getPost(postId); + if (post != null) { + return ResponseEntity.ok(postService.getPost(postId)); + } else { + return ResponseEntity.notFound().build(); + } } // POST /posts @@ -40,13 +45,23 @@ public ResponseEntity updatePost( @PathVariable("postId")Integer postId, @RequestBody PostRequest postRequest ) { - return ResponseEntity.ok(postService.updatePost(postId, postRequest)); + Post post = postService.getPost(postId); + if (post != null) { + return ResponseEntity.ok(postService.updatePost(postId, postRequest)); + } else { + return ResponseEntity.notFound().build(); + } } // DELETE /posts/{postId} @DeleteMapping("{postId}") public ResponseEntity deletePost(@PathVariable("postId") Integer postId) { - postService.deletePost(postId); - return ResponseEntity.noContent().build(); + Post post = postService.getPost(postId); + if (post != null) { + postService.deletePost(postId); + return ResponseEntity.noContent().build(); + } else { + return ResponseEntity.notFound().build(); + } } } From 3e267b59a416a4a61d1299d4722e3f1ca7424500 Mon Sep 17 00:00:00 2001 From: Hyeonggon Yoo <42.hyeyoo@gmail.com> Date: Mon, 6 May 2024 17:58:12 +0900 Subject: [PATCH 2/4] Update deployment_scp.yml Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com> --- .github/workflows/deployment_scp.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/deployment_scp.yml b/.github/workflows/deployment_scp.yml index 8d91ebb..c77b645 100644 --- a/.github/workflows/deployment_scp.yml +++ b/.github/workflows/deployment_scp.yml @@ -46,10 +46,10 @@ jobs: - name: Send jar to remote server uses: appleboy/scp-action@master with: - host: {나의 public ip} - username: {나의 userName} + host: 34.64.125.87 + username: g42_hyeyoo source: "devlog_springboot-0.0.1-SNAPSHOT.jar" - target: "/home/{나의 userName}" + target: "/home/g42_hyeyoo" key: ${{ secrets.PRIVATE_KEY }} run-app: @@ -61,16 +61,16 @@ jobs: - name: Move deploy.sh uses: appleboy/scp-action@master with: - host: {나의 public ip} - username: {나의 userName} + host: 34.64.125.87 + username: g42_hyeyoo source: "deploy.sh" - target: "/home/{나의 userName}" + target: "/home/g42_hyeyoo" key: ${{ secrets.PRIVATE_KEY }} - name: Execute script uses: appleboy/ssh-action@master with: - username: {나의 userName} - host: {나의 public ip} + username: g42_hyeyoo + host: 34.64.125.87 key: ${{ secrets.PRIVATE_KEY }} script_stop: true - script: cd /home/{나의 userName} && chmod +x deploy.sh && ./deploy.sh + script: cd /home/g42_hyeyoo && chmod +x deploy.sh && ./deploy.sh From e3281cb0895f49b7f942d92f68b3a353b7f8a408 Mon Sep 17 00:00:00 2001 From: Hyeonggon Yoo <42.hyeyoo@gmail.com> Date: Mon, 6 May 2024 18:12:31 +0900 Subject: [PATCH 3/4] Add /projects Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com> --- .../controller/ProjectController.java | 46 ++++++++++++++++ .../repository/ProjectRepository.java | 13 +++++ .../service/ProjectService.java | 55 +++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 src/main/java/com/com/cnu/devlog_springboot/controller/ProjectController.java create mode 100644 src/main/java/com/com/cnu/devlog_springboot/repository/ProjectRepository.java create mode 100644 src/main/java/com/com/cnu/devlog_springboot/service/ProjectService.java diff --git a/src/main/java/com/com/cnu/devlog_springboot/controller/ProjectController.java b/src/main/java/com/com/cnu/devlog_springboot/controller/ProjectController.java new file mode 100644 index 0000000..a3f2bd3 --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/controller/ProjectController.java @@ -0,0 +1,46 @@ +package com.com.cnu.devlog_springboot.controller; + +import com.com.cnu.devlog_springboot.model.Project; +import com.com.cnu.devlog_springboot.model.request.ProjectRequest; +import com.com.cnu.devlog_springboot.service.ProjectService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/projects") +@RequiredArgsConstructor +public class ProjectController { + // GET /projects + public final ProjectService projectService; + + @GetMapping + public List getAllProjects() { + return projectService.getAllProjects(); + } + + @GetMapping("{projectId}") + public ResponseEntity getProjectById(@PathVariable Integer projectId) { + Project project = projectService.getProject(projectId); + return ResponseEntity.ok(project); + } + + @PostMapping + public ResponseEntity createProject(@RequestBody ProjectRequest projectRequest) { + return ResponseEntity.ok(projectService.createProject(projectRequest)); + } + + @PutMapping("{projectId}") + public ResponseEntity updateProject(@PathVariable Integer projectId, @RequestBody ProjectRequest projectRequest) { + Project project = projectService.updateProject(projectId, projectRequest); + return ResponseEntity.ok(project); + } + + @DeleteMapping("{projectId}") + public ResponseEntity deleteProject(@PathVariable Integer projectId) { + projectService.deleteProject(projectId); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/com/com/cnu/devlog_springboot/repository/ProjectRepository.java b/src/main/java/com/com/cnu/devlog_springboot/repository/ProjectRepository.java new file mode 100644 index 0000000..5e312db --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/repository/ProjectRepository.java @@ -0,0 +1,13 @@ +package com.com.cnu.devlog_springboot.repository; + +import com.com.cnu.devlog_springboot.model.Project; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ProjectRepository extends JpaRepository { + // Project save(Project project); + // List findAll(); + // Optional findById(Integer projectId); + // void delete(Project project); +} diff --git a/src/main/java/com/com/cnu/devlog_springboot/service/ProjectService.java b/src/main/java/com/com/cnu/devlog_springboot/service/ProjectService.java new file mode 100644 index 0000000..b872604 --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/service/ProjectService.java @@ -0,0 +1,55 @@ +package com.com.cnu.devlog_springboot.service; + +import com.com.cnu.devlog_springboot.exception.DevlogException; +import com.com.cnu.devlog_springboot.model.Project; +import com.com.cnu.devlog_springboot.model.request.ProjectRequest; +import com.com.cnu.devlog_springboot.repository.ProjectRepository; +import com.com.cnu.devlog_springboot.type.ErrorCode; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class ProjectService { + private final ProjectRepository projectRepository; + + public Project createProject(ProjectRequest projectRequest) { + return projectRepository.save( + new Project(null, + projectRequest.title(), + projectRequest.summary(), + projectRequest.contents(), + projectRequest.startDate(), + projectRequest.endDate()) + ); + } + + public Project getProject(Integer projectId) { + return projectRepository.findById(projectId).orElseThrow(() + -> new DevlogException(ErrorCode.PROJECT_NOT_FOUND)); + } + + public List getAllProjects() { + return projectRepository.findAll(); + } + + public Project updateProject(Integer projectId, ProjectRequest projectRequest) { + return projectRepository.findById(projectId) + .map(project -> { + project.setTitle(projectRequest.title()); + project.setContents(projectRequest.contents()); + project.setSummary(projectRequest.summary()); + project.setStartDate(projectRequest.startDate()); + project.setEndDate(projectRequest.endDate()); + return projectRepository.save(project); + }).orElse(null); + } + + public void deleteProject(Integer projectId) { + Project project = projectRepository.findById(projectId) + .orElseThrow(() -> new DevlogException(ErrorCode.PROJECT_NOT_FOUND)); + projectRepository.delete(project); + } +} From ed2055c5ea1030779a25a471d877be22e63aa6d2 Mon Sep 17 00:00:00 2001 From: Hyeonggon Yoo <42.hyeyoo@gmail.com> Date: Mon, 6 May 2024 18:11:54 +0900 Subject: [PATCH 4/4] Better error handling Signed-off-by: Hyeonggon Yoo <42.hyeyoo@gmail.com> --- .../controller/PostController.java | 23 +++------------ .../exception/DevlogException.java | 11 +++++++ .../exception/GlobalExceptionHandler.java | 29 +++++++++++++++++++ .../model/ErrorResponse.java | 9 ++++++ .../service/PostService.java | 11 ++++--- .../service/ProjectService.java | 2 +- .../cnu/devlog_springboot/type/ErrorCode.java | 20 +++++++++++++ 7 files changed, 81 insertions(+), 24 deletions(-) create mode 100644 src/main/java/com/com/cnu/devlog_springboot/exception/DevlogException.java create mode 100644 src/main/java/com/com/cnu/devlog_springboot/exception/GlobalExceptionHandler.java create mode 100644 src/main/java/com/com/cnu/devlog_springboot/model/ErrorResponse.java create mode 100644 src/main/java/com/com/cnu/devlog_springboot/type/ErrorCode.java diff --git a/src/main/java/com/com/cnu/devlog_springboot/controller/PostController.java b/src/main/java/com/com/cnu/devlog_springboot/controller/PostController.java index 5b8284b..7d6847f 100644 --- a/src/main/java/com/com/cnu/devlog_springboot/controller/PostController.java +++ b/src/main/java/com/com/cnu/devlog_springboot/controller/PostController.java @@ -24,12 +24,7 @@ public ResponseEntity> getPosts() { // GET /posts/{postId} @GetMapping("{postId}") public ResponseEntity getPost(@PathVariable("postId")Integer postId) { - Post post = postService.getPost(postId); - if (post != null) { - return ResponseEntity.ok(postService.getPost(postId)); - } else { - return ResponseEntity.notFound().build(); - } + return ResponseEntity.ok(postService.getPost(postId)); } // POST /posts @@ -45,23 +40,13 @@ public ResponseEntity updatePost( @PathVariable("postId")Integer postId, @RequestBody PostRequest postRequest ) { - Post post = postService.getPost(postId); - if (post != null) { - return ResponseEntity.ok(postService.updatePost(postId, postRequest)); - } else { - return ResponseEntity.notFound().build(); - } + return ResponseEntity.ok(postService.updatePost(postId, postRequest)); } // DELETE /posts/{postId} @DeleteMapping("{postId}") public ResponseEntity deletePost(@PathVariable("postId") Integer postId) { - Post post = postService.getPost(postId); - if (post != null) { - postService.deletePost(postId); - return ResponseEntity.noContent().build(); - } else { - return ResponseEntity.notFound().build(); - } + postService.deletePost(postId); + return ResponseEntity.noContent().build(); } } diff --git a/src/main/java/com/com/cnu/devlog_springboot/exception/DevlogException.java b/src/main/java/com/com/cnu/devlog_springboot/exception/DevlogException.java new file mode 100644 index 0000000..9da0b4e --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/exception/DevlogException.java @@ -0,0 +1,11 @@ +package com.com.cnu.devlog_springboot.exception; + +import com.com.cnu.devlog_springboot.type.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class DevlogException extends RuntimeException { + private final ErrorCode errorCode; +} diff --git a/src/main/java/com/com/cnu/devlog_springboot/exception/GlobalExceptionHandler.java b/src/main/java/com/com/cnu/devlog_springboot/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..0c66785 --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/exception/GlobalExceptionHandler.java @@ -0,0 +1,29 @@ +package com.com.cnu.devlog_springboot.exception; + +import com.com.cnu.devlog_springboot.model.ErrorResponse; +import com.com.cnu.devlog_springboot.type.ErrorCode; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(DevlogException.class) + public ResponseEntity handleDevlogException( + final HttpServletRequest request, + final DevlogException e + ) { + final ErrorCode errorCode = e.getErrorCode(); + return ResponseEntity.status(e.getErrorCode().getHttpStatus()) + .body( + new ErrorResponse( + errorCode.getDescription(), + errorCode.getHttpStatus().value(), + errorCode.getErrorCode(), + request.getRequestURI() + ) + ); + } +} diff --git a/src/main/java/com/com/cnu/devlog_springboot/model/ErrorResponse.java b/src/main/java/com/com/cnu/devlog_springboot/model/ErrorResponse.java new file mode 100644 index 0000000..55e9a62 --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/model/ErrorResponse.java @@ -0,0 +1,9 @@ +package com.com.cnu.devlog_springboot.model; + +public record ErrorResponse( + String title, + Integer status, + Integer code, + String instance +) { +} \ No newline at end of file diff --git a/src/main/java/com/com/cnu/devlog_springboot/service/PostService.java b/src/main/java/com/com/cnu/devlog_springboot/service/PostService.java index 3823d7a..4a289b9 100644 --- a/src/main/java/com/com/cnu/devlog_springboot/service/PostService.java +++ b/src/main/java/com/com/cnu/devlog_springboot/service/PostService.java @@ -1,8 +1,10 @@ package com.com.cnu.devlog_springboot.service; +import com.com.cnu.devlog_springboot.exception.DevlogException; import com.com.cnu.devlog_springboot.model.Post; import com.com.cnu.devlog_springboot.model.request.PostRequest; import com.com.cnu.devlog_springboot.repository.PostRepository; +import com.com.cnu.devlog_springboot.type.ErrorCode; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -33,16 +35,17 @@ public Post updatePost(Integer postId, PostRequest postRequest) { post.setContents(postRequest.contents()); return postRepository.save(post); }) - .orElse(null); + .orElseThrow(() -> new DevlogException(ErrorCode.POST_NOT_FOUND)); } public Post getPost(Integer postId) { return postRepository.findById(postId) - .orElse(null); + .orElseThrow(() -> new DevlogException(ErrorCode.POST_NOT_FOUND)); } public void deletePost(Integer postId) { - postRepository.findById(postId) - .ifPresent(postRepository::delete); + Post post = postRepository.findById(postId) + .orElseThrow(() -> new DevlogException(ErrorCode.POST_NOT_FOUND)); + postRepository.delete(post); } } diff --git a/src/main/java/com/com/cnu/devlog_springboot/service/ProjectService.java b/src/main/java/com/com/cnu/devlog_springboot/service/ProjectService.java index b872604..6258533 100644 --- a/src/main/java/com/com/cnu/devlog_springboot/service/ProjectService.java +++ b/src/main/java/com/com/cnu/devlog_springboot/service/ProjectService.java @@ -44,7 +44,7 @@ public Project updateProject(Integer projectId, ProjectRequest projectRequest) { project.setStartDate(projectRequest.startDate()); project.setEndDate(projectRequest.endDate()); return projectRepository.save(project); - }).orElse(null); + }).orElseThrow(() -> new DevlogException(ErrorCode.PROJECT_NOT_FOUND)); } public void deleteProject(Integer projectId) { diff --git a/src/main/java/com/com/cnu/devlog_springboot/type/ErrorCode.java b/src/main/java/com/com/cnu/devlog_springboot/type/ErrorCode.java new file mode 100644 index 0000000..62d29b1 --- /dev/null +++ b/src/main/java/com/com/cnu/devlog_springboot/type/ErrorCode.java @@ -0,0 +1,20 @@ +package com.com.cnu.devlog_springboot.type; + +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +public enum ErrorCode { + POST_NOT_FOUND(HttpStatus.NOT_FOUND, 404, "해당 게시글을 찾을 수 없습니다."), + PROJECT_NOT_FOUND(HttpStatus.NOT_FOUND, 404, "해당 프로젝트 글을 찾을 수 없습니다."); + + private final HttpStatus httpStatus; + private final Integer errorCode; + private final String description; + + ErrorCode(final HttpStatus httpStatus, final Integer errorCode, final String description) { + this.httpStatus = httpStatus; + this.errorCode = errorCode; + this.description = description; + } +}