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

[BE] 예외메시지 구체화 #161

Merged
merged 6 commits into from
Aug 1, 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
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import server.haengdong.application.request.MemberActionSaveAppRequest;
import server.haengdong.application.request.MemberActionsSaveAppRequest;
import server.haengdong.domain.action.Action;
import server.haengdong.domain.action.CurrentMembers;
import server.haengdong.domain.action.MemberAction;
import server.haengdong.domain.action.MemberActionStatus;
import server.haengdong.domain.action.MemberGroupIdProvider;
Expand All @@ -22,11 +23,11 @@ public class MemberActionFactory {

public List<MemberAction> createMemberActions(
MemberActionsSaveAppRequest request,
List<MemberAction> memberActions,
CurrentMembers currentMembers,
Action action
) {
validateMemberNames(request);
validateActions(request, memberActions);
validateActions(request, currentMembers);

Long memberGroupId = memberGroupIdProvider.createGroupId();
List<MemberAction> createdMemberActions = new ArrayList<>();
Expand All @@ -51,32 +52,12 @@ private void validateMemberNames(MemberActionsSaveAppRequest request) {
}
}

private void validateActions(MemberActionsSaveAppRequest request, List<MemberAction> memberActions) {
List<MemberAction> reverseSortedMemberActions = memberActions.stream()
.sorted(Comparator.comparing(MemberAction::getSequence).reversed())
.toList();

for (MemberActionSaveAppRequest action : request.actions()) {
validateAction(action, reverseSortedMemberActions);
}
}
private void validateActions(MemberActionsSaveAppRequest request, CurrentMembers currentMembers) {
List<MemberActionSaveAppRequest> actions = request.actions();

private void validateAction(MemberActionSaveAppRequest request, List<MemberAction> memberActions) {
MemberActionStatus memberActionStatus = MemberActionStatus.of(request.status());
if (isInvalidStatus(memberActions, request.name(), memberActionStatus)) {
throw new HaengdongException(HaengdongErrorCode.INVALID_MEMBER_ACTION);
for (MemberActionSaveAppRequest action : actions) {
MemberActionStatus memberActionStatus = MemberActionStatus.of(action.status());
currentMembers.validate(action.name(), memberActionStatus);
}
}

private boolean isInvalidStatus(
List<MemberAction> memberActions,
String memberName,
MemberActionStatus memberActionStatus
) {
return memberActions.stream()
.filter(action -> action.isSameName(memberName))
.findFirst()
.map(action -> action.isSameStatus(memberActionStatus))
.orElse(MemberActionStatus.IN != memberActionStatus);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ public void saveMemberAction(String token, MemberActionsSaveAppRequest request)
Event event = findEvent(token);

List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event);
CurrentMembers currentMembers = CurrentMembers.of(findMemberActions);
Action action = createStartAction(event);
List<MemberAction> memberActions = memberActionFactory.createMemberActions(request, findMemberActions, action);
List<MemberAction> memberActions = memberActionFactory.createMemberActions(request, currentMembers, action);
memberActionRepository.saveAll(memberActions);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import server.haengdong.exception.HaengdongErrorCode;
import server.haengdong.exception.HaengdongException;

public class CurrentMembers {

Expand All @@ -14,7 +16,7 @@ public CurrentMembers() {
this(new HashSet<>());
}

private CurrentMembers(Set<String> members) {
protected CurrentMembers(Set<String> members) {
kunsanglee marked this conversation as resolved.
Show resolved Hide resolved
this.members = members;
}

Expand Down Expand Up @@ -52,6 +54,15 @@ public CurrentMembers addMemberAction(MemberAction memberAction) {
return new CurrentMembers(currentMembers);
}

public void validate(String memberName, MemberActionStatus memberActionStatus) {
if (memberActionStatus == MemberActionStatus.IN && members.contains(memberName)) {
throw new HaengdongException(HaengdongErrorCode.INVALID_MEMBER_IN_ACTION);
}
if (memberActionStatus == MemberActionStatus.OUT && !members.contains(memberName)) {
throw new HaengdongException(HaengdongErrorCode.INVALID_MEMBER_OUT_ACTION);
}
}

public boolean isEmpty() {
return members.isEmpty();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package server.haengdong.exception;

public record ErrorResponse(
String code,
String message
) {

public static ErrorResponse of(String message) {
return new ErrorResponse(message);
public static ErrorResponse of(HaengdongErrorCode errorCode) {
return new ErrorResponse(errorCode.getCode(), errorCode.getMessage());
}

public static ErrorResponse of(HaengdongErrorCode errorCode, String message){
return new ErrorResponse(errorCode.getCode(), message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,51 @@
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.resource.NoResourceFoundException;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public ResponseEntity<ErrorResponse> haengdongException() {
@ExceptionHandler({HttpRequestMethodNotSupportedException.class, NoResourceFoundException.class})
public ResponseEntity<ErrorResponse> noResourceException() {
return ResponseEntity.badRequest()
.body(ErrorResponse.of(HaengdongErrorCode.BAD_REQUEST.getMessage()));
.body(ErrorResponse.of(HaengdongErrorCode.NO_RESOURCE_REQUEST));
}

@ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<ErrorResponse> httpMessageNotReadableException() {
return ResponseEntity.badRequest()
.body(ErrorResponse.of(HaengdongErrorCode.MESSAGE_NOT_READABLE));
}

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
log.info(e.getMessage(), e);
String errorMessage = e.getFieldErrors().stream()
.map(error -> error.getField() + " " + error.getDefaultMessage())
.collect(Collectors.joining(", "));

return ResponseEntity.badRequest()
.body(ErrorResponse.of(errorMessage));
.body(ErrorResponse.of(HaengdongErrorCode.BAD_REQUEST, errorMessage));
}

@ExceptionHandler(HaengdongException.class)
public ResponseEntity<ErrorResponse> haengdongException(HaengdongException e) {
return ResponseEntity.status(e.getStatusCode())
.body(ErrorResponse.of(e.getMessage()));
log.info(e.getMessage(), e);
return ResponseEntity.badRequest()
.body(ErrorResponse.of(e.getErrorCode()));
}

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception e) {
log.error(e.getMessage(), e);
return ResponseEntity.internalServerError()
.body(ErrorResponse.of(HaengdongErrorCode.INTERNAL_SERVER_ERROR.getMessage()));
.body(ErrorResponse.of(HaengdongErrorCode.INTERNAL_SERVER_ERROR));
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
package server.haengdong.exception;

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

@Getter
public enum HaengdongErrorCode {
BAD_REQUEST(HttpStatus.BAD_REQUEST, "잘못된 요청입니다."),
DUPLICATED_MEMBER_ACTION(HttpStatus.BAD_REQUEST, "올바르지 않은 인원 요청입니다."),
INVALID_MEMBER_ACTION(HttpStatus.BAD_REQUEST, "잘못된 맴버 액션입니다."),

NOT_FOUND_EVENT(HttpStatus.NOT_FOUND, "존재하지 않는 행사입니다."),

INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "서버 내부에서 에러가 발생했습니다."),
BAD_REQUEST("R_001", "잘못된 요청입니다."),
NO_RESOURCE_REQUEST("R_002", "잘못된 엔드포인트입니다."),
MESSAGE_NOT_READABLE("R_003", "읽을 수 없는 요청 형식입니다."),
DUPLICATED_MEMBER_ACTION("MA_001", "중복된 인원이 존재합니다."),
INVALID_MEMBER_IN_ACTION("MA_002", "현재 참여하고 있는 인원이 존재합니다."),
INVALID_MEMBER_OUT_ACTION("MA_003", "현재 참여하고 있지 않는 인원이 존재합니다."),
NOT_FOUND_EVENT("EV_400", "존재하지 않는 행사입니다."),
INTERNAL_SERVER_ERROR("S_001", "서버 내부에서 에러가 발생했습니다."),
;

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

HaengdongErrorCode(HttpStatus httpStatus, String message) {
this.httpStatus = httpStatus;
HaengdongErrorCode(String code, String message) {
this.code = code;
this.message = message;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package server.haengdong.exception;

import lombok.Getter;
import org.springframework.http.HttpStatusCode;

@Getter
public class HaengdongException extends RuntimeException {
Expand All @@ -18,10 +17,6 @@ public HaengdongException(HaengdongErrorCode errorCode, String message) {
this.message = message;
}

public HttpStatusCode getStatusCode() {
return errorCode.getHttpStatus();
}

@Override
public String getMessage() {
if (message == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import server.haengdong.application.request.MemberActionSaveAppRequest;
import server.haengdong.application.request.MemberActionsSaveAppRequest;
import server.haengdong.domain.action.Action;
import server.haengdong.domain.action.CurrentMembers;
import server.haengdong.domain.event.Event;
import server.haengdong.domain.action.MemberAction;
import server.haengdong.domain.action.MemberActionStatus;
Expand Down Expand Up @@ -56,10 +57,12 @@ void createMemberActionsTest() {

MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest(
List.of(new MemberActionSaveAppRequest("토다리", "OUT")));

List<MemberAction> unorderedMemberActions = List.of(memberAction2, memberAction1);
CurrentMembers currentMembers = CurrentMembers.of(unorderedMemberActions);
Action startAction = new Action(event, 3L);

assertThatThrownBy(() -> memberActionFactory.createMemberActions(request, unorderedMemberActions, startAction))
assertThatThrownBy(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction))
.isInstanceOf(HaengdongException.class);
}

Expand All @@ -75,8 +78,10 @@ void createMemberActionsTest1() {
List.of(new MemberActionSaveAppRequest("토다리", "OUT")));
Action startAction = new Action(event, 2L);

CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction));
List<MemberAction> memberActions = memberActionFactory.createMemberActions(memberActionsSaveAppRequest,
List.of(memberAction), startAction);
currentMembers, startAction
);

assertThat(memberActions).hasSize(1)
.extracting(MemberAction::getAction, MemberAction::getMemberName, MemberAction::getStatus)
Expand All @@ -96,8 +101,9 @@ void createMemberActionsTest2() {
MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest(
List.of(new MemberActionSaveAppRequest("토다리", "OUT")));
Action startAction = new Action(event, 2L);
CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction));

assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction))
assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction))
.doesNotThrowAnyException();
}

Expand All @@ -115,10 +121,9 @@ void createMemberActionsTest3() {
MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest(
List.of(new MemberActionSaveAppRequest("토다리", "IN")));
Action startAction = new Action(event, 3L);
CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction1, memberAction2));

assertThatCode(
() -> memberActionFactory.createMemberActions(request, List.of(memberAction1, memberAction2),
startAction))
assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction))
.doesNotThrowAnyException();
}

Expand All @@ -133,8 +138,9 @@ void createMemberActionsTest4() {
MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest(
List.of(new MemberActionSaveAppRequest("쿠키", "IN")));
Action startAction = new Action(event, 2L);
CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction));

assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction))
assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction))
.doesNotThrowAnyException();
}

Expand All @@ -146,8 +152,10 @@ void createMemberActionTest5() {
MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest(
List.of(new MemberActionSaveAppRequest("쿠키", "OUT")));
Action startAction = new Action(event, 2L);
CurrentMembers currentMembers = CurrentMembers.of(List.of());

assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(), startAction))
assertThatCode(
() -> memberActionFactory.createMemberActions(request, currentMembers, startAction))
.isInstanceOf(HaengdongException.class);
}

Expand All @@ -162,8 +170,9 @@ void createMemberActionTest6() {
MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest(
List.of(new MemberActionSaveAppRequest("쿠키", "IN")));
Action startAction = new Action(event, 2L);
CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction));

assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction))
assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction))
.isInstanceOf(HaengdongException.class);
}

Expand All @@ -173,11 +182,15 @@ void createMemberActionTest7() {
Event event = eventRepository.save(new Event("test", "TOKEN"));

MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest(
List.of(new MemberActionSaveAppRequest("쿠키", "IN"),
new MemberActionSaveAppRequest("쿠키", "IN")));
List.of(
new MemberActionSaveAppRequest("쿠키", "IN"),
new MemberActionSaveAppRequest("쿠키", "IN")
));
Action startAction = new Action(event, 1L);
CurrentMembers currentMembers = CurrentMembers.of(List.of());

assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(), startAction))
assertThatCode(
() -> memberActionFactory.createMemberActions(request, currentMembers, startAction))
.isInstanceOf(HaengdongException.class);
}

Expand All @@ -190,11 +203,14 @@ void createMemberActionTest8() {
memberActionRepository.save(memberAction);

MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest(
List.of(new MemberActionSaveAppRequest("쿠키", "OUT"),
new MemberActionSaveAppRequest("쿠키", "OUT")));
List.of(
new MemberActionSaveAppRequest("쿠키", "OUT"),
new MemberActionSaveAppRequest("쿠키", "OUT")
));
Action startAction = new Action(event, 2L);
CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction));

assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction))
assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction))
.isInstanceOf(HaengdongException.class);
}

Expand All @@ -207,11 +223,14 @@ void createMemberActionTest9() {
memberActionRepository.save(memberAction);

MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest(
List.of(new MemberActionSaveAppRequest("쿠키", "IN"),
new MemberActionSaveAppRequest("쿠키", "OUT")));
List.of(
new MemberActionSaveAppRequest("쿠키", "IN"),
new MemberActionSaveAppRequest("쿠키", "OUT")
));
Action startAction = new Action(event, 2L);
CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction));

assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction))
assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction))
.isInstanceOf(HaengdongException.class);
}
}
Loading
Loading