Skip to content

Commit

Permalink
feat: Article 생성, 에러 코드 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
kyeong-hyeok committed Sep 9, 2023
1 parent a6ad7a5 commit 0ec3713
Show file tree
Hide file tree
Showing 12 changed files with 187 additions and 9 deletions.
24 changes: 24 additions & 0 deletions src/main/java/com/teamB/pcs/common/dto/ResponseDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.teamB.pcs.common.dto;

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

import java.io.Serializable;

public record ResponseDto<T>(T data) implements Serializable {
public static <T> ResponseEntity<T> ok(T data) {
return ResponseEntity.ok(data);
}

public static <T> ResponseEntity<T> created(T data) {
return ResponseEntity
.status(HttpStatus.CREATED)
.body(data);
}

public static ResponseEntity<Void> noContent() {
return ResponseEntity
.status(HttpStatus.NO_CONTENT)
.build();
}
}
10 changes: 7 additions & 3 deletions src/main/java/com/teamB/pcs/controller/ArticleController.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.teamB.pcs.controller;

import com.teamB.pcs.common.dto.ResponseDto;
import com.teamB.pcs.dto.request.ArticleRequest;
import com.teamB.pcs.dto.request.ArticleSaveRequestDto;
import com.teamB.pcs.dto.response.ArticleListResponse;
import com.teamB.pcs.dto.response.ArticleResponse;
import com.teamB.pcs.service.ArticleService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

Expand All @@ -21,9 +24,10 @@ public ArticleListResponse getAll(){
return articleService.getAll();
}

@PostMapping("")
public void create(@RequestBody ArticleRequest articleRequest){
articleService.create(articleRequest);
@PostMapping()
public ResponseEntity<Void> create(@RequestBody ArticleSaveRequestDto articleSaveRequestDto){
articleService.create(articleSaveRequestDto);
return ResponseDto.noContent();
}

@GetMapping("/{articleId}")
Expand Down
10 changes: 6 additions & 4 deletions src/main/java/com/teamB/pcs/domain/Article.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,26 @@ public class Article {

private String body;

private List<String> tagList;//따로 태그 엔티티를 파야하나?
private List<Tag> tags;

@CreationTimestamp
private LocalDateTime createdAt;

@UpdateTimestamp
private LocalDateTime updatedAt;

@Builder
public Article(String title, String description, String body) {//태그도 추가되게해야됨

public void update(String title, String description, String body) {
this.title = title;
this.description = description;
this.body = body;
}

public void update(String title, String description, String body) {
@Builder
public Article(String title, String description, String body, List<Tag> tags) {
this.title = title;
this.description = description;
this.body = body;
this.tags = tags;
}
}
31 changes: 31 additions & 0 deletions src/main/java/com/teamB/pcs/domain/Tag.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.teamB.pcs.domain;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.teamB.pcs.error.ErrorCode;
import com.teamB.pcs.error.exception.BusinessException;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

@RequiredArgsConstructor
@Getter
public enum Tag {
STUDY, HEALTH, DRINK, OTHER;

@JsonCreator
public static List<Tag> create(List<String> requestValue) {
List<Tag> tags = new ArrayList<>();
for (String r : requestValue) {
Tag tag = Stream.of(values())
.filter(v -> v.toString().equalsIgnoreCase(r))
.findFirst()
.orElseThrow(() -> new BusinessException(ErrorCode.INVALID_TAG));
tags.add(tag);
}
return tags;
}

}
18 changes: 18 additions & 0 deletions src/main/java/com/teamB/pcs/dto/request/ArticleSaveRequestDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.teamB.pcs.dto.request;

import com.teamB.pcs.domain.Article;
import com.teamB.pcs.domain.Tag;

import java.util.List;

public record ArticleSaveRequestDto(String title, String description, String body, List<String> tags) {

public Article toEntity(String title, String description, String body, List<Tag> tags) {
return Article.builder()
.title(title)
.description(description)
.body(body)
.tags(tags)
.build();
}
}
5 changes: 3 additions & 2 deletions src/main/java/com/teamB/pcs/dto/response/ArticleResponse.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.teamB.pcs.dto.response;

import com.teamB.pcs.domain.Article;
import com.teamB.pcs.domain.Tag;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand All @@ -18,7 +19,7 @@ public class ArticleResponse {

private String body;

private List<String> tagList;
private List<Tag> tagList;

private LocalDateTime createdAt;//반환할때 LocalDateTime으로 해도되나?

Expand All @@ -29,7 +30,7 @@ public ArticleResponse(Article article){
title=article.getTitle();
description=article.getDescription();
body=article.getBody();
tagList=article.getTagList();
tagList=article.getTags();
createdAt=article.getCreatedAt();
updatedAt=article.getUpdatedAt();
}
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/com/teamB/pcs/error/ErrorCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.teamB.pcs.error;

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

import static org.springframework.http.HttpStatus.*;
import static org.springframework.http.HttpStatus.NOT_FOUND;

@Getter
@RequiredArgsConstructor
public enum ErrorCode {

INVALID_TAG(BAD_REQUEST, "태그를 찾을 수 없습니다");


private final int code;
private final String message;

ErrorCode(HttpStatus code, String message) {
this.code = code.value();
this.message = message;
}
}
8 changes: 8 additions & 0 deletions src/main/java/com/teamB/pcs/error/dto/ErrorResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.teamB.pcs.error.dto;

public record ErrorResponse(int code, String message) {
public static ErrorResponse of(int code, String message){
return new ErrorResponse(code, message);
}

}
15 changes: 15 additions & 0 deletions src/main/java/com/teamB/pcs/error/exception/BusinessException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.teamB.pcs.error.exception;

import com.teamB.pcs.error.ErrorCode;
import lombok.Getter;

@Getter
public class BusinessException extends RuntimeException{

private final int code;

public BusinessException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.code = errorCode.getCode();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.teamB.pcs.error.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;
import java.util.stream.Collectors;
import com.teamB.pcs.error.dto.ErrorResponse;
import static org.springframework.http.HttpStatus.BAD_REQUEST;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler
public ResponseEntity<ErrorResponse> handle(final Exception e) {
log.error("Internal Error occurred", e);
return ResponseEntity.internalServerError().body(ErrorResponse.of(500, e.getMessage()));
}

@ExceptionHandler
public ResponseEntity<ErrorResponse> handle(final BusinessException e) {
log.info("businessException: {}", e);
return ResponseEntity.status(e.getCode()).body(ErrorResponse.of(e.getCode(), e.getMessage()));
}

@ExceptionHandler
public ResponseEntity<ErrorResponse> handle(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
String firstErrorMessage = bindingResult.getFieldErrors().get(0).getDefaultMessage();

List<String> errorList = bindingResult.getFieldErrors().stream().map(err -> err.getDefaultMessage()).collect(Collectors.toList());
log.warn("MethodArgumentNotValidExceptionException = {}", errorList);

return ResponseEntity.status(BAD_REQUEST).body(ErrorResponse.of(BAD_REQUEST.value(), firstErrorMessage));
}
}
8 changes: 8 additions & 0 deletions src/main/java/com/teamB/pcs/service/ArticleService.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.teamB.pcs.service;

import com.teamB.pcs.domain.Article;
import com.teamB.pcs.domain.Tag;
import com.teamB.pcs.dto.request.ArticleRequest;
import com.teamB.pcs.dto.request.ArticleSaveRequestDto;
import com.teamB.pcs.dto.response.ArticleListResponse;
import com.teamB.pcs.dto.response.ArticleResponse;
import com.teamB.pcs.repository.ArticleRepository;
Expand All @@ -17,6 +19,12 @@
public class ArticleService {
private final ArticleRepository articleRepository;

public void create(ArticleSaveRequestDto request) {
List<Tag> tags = Tag.create(request.tags());
Article article = request.toEntity(request.title(), request.description(), request.body(), tags);
articleRepository.save(article);
}

public ArticleListResponse getAll() {
List<ArticleResponse> articleResponses = articleRepository.findAll().stream()
.map(ArticleResponse::new)
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
spring:
profiles:
active:
local
group:
local-env:
- local
Expand Down

0 comments on commit 0ec3713

Please sign in to comment.