From 988b1138f14a0459d3efe57d5cb6e1d08f520c42 Mon Sep 17 00:00:00 2001 From: Hanjaemo <110653660+Hanjaemo@users.noreply.github.com> Date: Thu, 13 Jun 2024 02:27:19 +0900 Subject: [PATCH 1/6] =?UTF-8?q?refactor:=20argument=20reolver=EB=A5=BC=20?= =?UTF-8?q?=EC=9D=B4=EC=9A=A9=ED=95=B4,=20=EC=BF=BC=EB=A6=AC=20=ED=8C=8C?= =?UTF-8?q?=EB=9D=BC=EB=AF=B8=ED=84=B0=EB=A1=9C=20=EC=A0=84=EB=8B=AC?= =?UTF-8?q?=EB=90=98=EB=8D=98=20tags=EB=A5=BC=20=EC=9D=BC=EA=B8=89=20?= =?UTF-8?q?=EC=BB=AC=EB=A0=89=EC=85=98=EC=9C=BC=EB=A1=9C=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/web/TagsArgumentResolver.java | 30 +++++++++++++++++++ .../application/CollectingBoxService.java | 26 +++++----------- .../module/collectingbox/domain/Tags.java | 22 ++++++++++++++ .../presentation/CollectingBoxController.java | 5 ++-- .../application/CollectingBoxServiceTest.java | 10 +++---- 5 files changed, 67 insertions(+), 26 deletions(-) create mode 100644 src/main/java/contest/collectingbox/global/config/web/TagsArgumentResolver.java create mode 100644 src/main/java/contest/collectingbox/module/collectingbox/domain/Tags.java diff --git a/src/main/java/contest/collectingbox/global/config/web/TagsArgumentResolver.java b/src/main/java/contest/collectingbox/global/config/web/TagsArgumentResolver.java new file mode 100644 index 0000000..c744151 --- /dev/null +++ b/src/main/java/contest/collectingbox/global/config/web/TagsArgumentResolver.java @@ -0,0 +1,30 @@ +package contest.collectingbox.global.config.web; + +import contest.collectingbox.module.collectingbox.domain.Tag; +import contest.collectingbox.module.collectingbox.domain.Tags; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.core.MethodParameter; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +import java.util.Arrays; +import java.util.List; + +public class TagsArgumentResolver implements HandlerMethodArgumentResolver { + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.getParameterType().equals(Tags.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { + HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); + List tags = Arrays.stream(request.getParameter("tags").split(",")) + .map(Tag::valueOf) + .toList(); + return new Tags(tags); + } +} diff --git a/src/main/java/contest/collectingbox/module/collectingbox/application/CollectingBoxService.java b/src/main/java/contest/collectingbox/module/collectingbox/application/CollectingBoxService.java index 17012e0..947268e 100644 --- a/src/main/java/contest/collectingbox/module/collectingbox/application/CollectingBoxService.java +++ b/src/main/java/contest/collectingbox/module/collectingbox/application/CollectingBoxService.java @@ -1,11 +1,10 @@ package contest.collectingbox.module.collectingbox.application; -import contest.collectingbox.global.exception.CollectingBoxException; -import contest.collectingbox.global.exception.ErrorCode; import contest.collectingbox.global.utils.GeometryUtil; import contest.collectingbox.module.collectingbox.domain.CollectingBox; import contest.collectingbox.module.collectingbox.domain.CollectingBoxRepository; import contest.collectingbox.module.collectingbox.domain.Tag; +import contest.collectingbox.module.collectingbox.domain.Tags; import contest.collectingbox.module.collectingbox.dto.CollectingBoxDetailResponse; import contest.collectingbox.module.collectingbox.dto.CollectingBoxResponse; import contest.collectingbox.module.location.domain.DongInfo; @@ -19,8 +18,6 @@ import java.util.List; import java.util.stream.Collectors; -import static contest.collectingbox.global.exception.ErrorCode.NOT_FOUND_COLLECTING_BOX; - @Service @RequiredArgsConstructor public class CollectingBoxService { @@ -34,14 +31,9 @@ public class CollectingBoxService { @Transactional(readOnly = true) public List findCollectingBoxesWithinArea(final Double latitude, final Double longitude, - final List tags) { - if (tags.isEmpty()) { - throw new CollectingBoxException(ErrorCode.NOT_SELECTED_TAG); - } - + final Tags tags) { Point center = GeometryUtil.toPoint(longitude, latitude); - - return collectingBoxRepository.findAllWithinArea(center, radius, tags) + return collectingBoxRepository.findAllWithinArea(center, radius, tags.toUnmodifiableList()) .stream() .map(CollectingBoxResponse::fromEntity) .collect(Collectors.toList()); @@ -53,25 +45,21 @@ public CollectingBoxDetailResponse findBoxDetailById(Long collectionId) { } @Transactional(readOnly = true) - public List searchCollectingBoxes(final String query, final List tags) { - if (tags.isEmpty()) { - throw new CollectingBoxException(ErrorCode.NOT_SELECTED_TAG); - } - + public List searchCollectingBoxes(final String query, final Tags tags) { // '강남구' if (query.endsWith("구")) { - return searchBySigunguNm(query, tags); + return searchBySigunguNm(query, tags.toUnmodifiableList()); } String[] splitQuery = query.split(" "); // '역삼1동' if (splitQuery.length == 1) { - return searchByDongNm(query, tags); + return searchByDongNm(query, tags.toUnmodifiableList()); } // '강남구 역삼1동' - return searchByDongNm(splitQuery[1], tags); + return searchByDongNm(splitQuery[1], tags.toUnmodifiableList()); } private List searchBySigunguNm(String query, List tags) { diff --git a/src/main/java/contest/collectingbox/module/collectingbox/domain/Tags.java b/src/main/java/contest/collectingbox/module/collectingbox/domain/Tags.java new file mode 100644 index 0000000..e74cb60 --- /dev/null +++ b/src/main/java/contest/collectingbox/module/collectingbox/domain/Tags.java @@ -0,0 +1,22 @@ +package contest.collectingbox.module.collectingbox.domain; + +import contest.collectingbox.global.exception.CollectingBoxException; +import contest.collectingbox.global.exception.ErrorCode; + +import java.util.Collections; +import java.util.List; + +public class Tags { + private final List tags; + + public Tags(List tags) { + if (tags == null || tags.isEmpty()) { + throw new CollectingBoxException(ErrorCode.NOT_SELECTED_TAG); + } + this.tags = tags; + } + + public List toUnmodifiableList() { + return Collections.unmodifiableList(tags); + } +} diff --git a/src/main/java/contest/collectingbox/module/collectingbox/presentation/CollectingBoxController.java b/src/main/java/contest/collectingbox/module/collectingbox/presentation/CollectingBoxController.java index 250d68b..e12ff90 100644 --- a/src/main/java/contest/collectingbox/module/collectingbox/presentation/CollectingBoxController.java +++ b/src/main/java/contest/collectingbox/module/collectingbox/presentation/CollectingBoxController.java @@ -3,6 +3,7 @@ import contest.collectingbox.global.common.ApiResponse; import contest.collectingbox.module.collectingbox.application.CollectingBoxService; import contest.collectingbox.module.collectingbox.domain.Tag; +import contest.collectingbox.module.collectingbox.domain.Tags; import contest.collectingbox.module.collectingbox.dto.CollectingBoxDetailResponse; import contest.collectingbox.module.collectingbox.dto.CollectingBoxResponse; import io.swagger.v3.oas.annotations.Operation; @@ -24,14 +25,14 @@ public class CollectingBoxController { @GetMapping public ApiResponse> findCollectingBoxesWithinArea(@RequestParam final Double latitude, @RequestParam final Double longitude, - @RequestParam final List tags) { + final Tags tags) { return ApiResponse.ok(collectingBoxService.findCollectingBoxesWithinArea(latitude, longitude, tags)); } @Operation(summary = "지역별 수거함 검색", description = "구/동 단위로 검색한 주소에 위치한 수거함 목록을 조회합니다.") @GetMapping("/search") public ApiResponse> searchCollectingBoxes(@RequestParam final String query, - @RequestParam final List tags) { + final Tags tags) { return ApiResponse.ok(collectingBoxService.searchCollectingBoxes(query, tags)); } diff --git a/src/test/java/contest/collectingbox/module/collectingbox/application/CollectingBoxServiceTest.java b/src/test/java/contest/collectingbox/module/collectingbox/application/CollectingBoxServiceTest.java index e428ba2..3b268d0 100644 --- a/src/test/java/contest/collectingbox/module/collectingbox/application/CollectingBoxServiceTest.java +++ b/src/test/java/contest/collectingbox/module/collectingbox/application/CollectingBoxServiceTest.java @@ -5,7 +5,7 @@ import contest.collectingbox.global.utils.GeometryUtil; import contest.collectingbox.module.collectingbox.domain.CollectingBox; import contest.collectingbox.module.collectingbox.domain.CollectingBoxRepository; -import contest.collectingbox.module.collectingbox.domain.Tag; +import contest.collectingbox.module.collectingbox.domain.Tags; import contest.collectingbox.module.collectingbox.dto.CollectingBoxDetailResponse; import contest.collectingbox.module.collectingbox.dto.CollectingBoxResponse; import contest.collectingbox.module.location.domain.Location; @@ -23,7 +23,7 @@ import java.util.Collections; import java.util.List; -import static contest.collectingbox.global.exception.ErrorCode.*; +import static contest.collectingbox.global.exception.ErrorCode.NOT_FOUND_COLLECTING_BOX; import static contest.collectingbox.module.collectingbox.domain.Tag.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; @@ -55,7 +55,7 @@ void setUp() { @DisplayName("위도와 경도를 기준으로 특정 반경에 위치한 수거함 목록 조회 성공") void findCollectingBoxesWithinArea_Success_withinArea() { // given - List tags = List.of(CLOTHES, LAMP_BATTERY, MEDICINE, TRASH); + Tags tags = new Tags(List.of(CLOTHES, LAMP_BATTERY, MEDICINE, TRASH)); CollectingBox box = CollectingBox.builder() .id(1L) @@ -64,7 +64,7 @@ void findCollectingBoxesWithinArea_Success_withinArea() { .build(); // when - when(collectingBoxRepository.findAllWithinArea(center, radius, tags)).thenReturn( + when(collectingBoxRepository.findAllWithinArea(center, radius, tags.toUnmodifiableList())).thenReturn( Collections.singletonList(box)); List result = @@ -79,7 +79,7 @@ void findCollectingBoxesWithinArea_Success_withinArea() { void findCollectingBoxesWithinArea_Fail_ByTagIsEmpty() { // when, then Assertions.assertThatThrownBy( - () -> collectingBoxService.findCollectingBoxesWithinArea(LATITUDE, LONGITUDE, List.of())) + () -> collectingBoxService.findCollectingBoxesWithinArea(LATITUDE, LONGITUDE, new Tags(List.of()))) .isInstanceOf(CollectingBoxException.class) .hasMessageContaining(ErrorCode.NOT_SELECTED_TAG.getMessage()); } From 60e2d1d21500ddc2009b6ea3b49438b780f1dcd3 Mon Sep 17 00:00:00 2001 From: Hanjaemo <110653660+Hanjaemo@users.noreply.github.com> Date: Thu, 13 Jun 2024 15:03:32 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=EC=BF=BC=EB=A6=AC=20=ED=8C=8C?= =?UTF-8?q?=EB=9D=BC=EB=AF=B8=ED=84=B0=20tags=20null=20=EC=B2=B4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/config/web/TagsArgumentResolver.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/contest/collectingbox/global/config/web/TagsArgumentResolver.java b/src/main/java/contest/collectingbox/global/config/web/TagsArgumentResolver.java index c744151..e3fabbb 100644 --- a/src/main/java/contest/collectingbox/global/config/web/TagsArgumentResolver.java +++ b/src/main/java/contest/collectingbox/global/config/web/TagsArgumentResolver.java @@ -4,6 +4,7 @@ import contest.collectingbox.module.collectingbox.domain.Tags; import jakarta.servlet.http.HttpServletRequest; import org.springframework.core.MethodParameter; +import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; @@ -22,6 +23,10 @@ public boolean supportsParameter(MethodParameter parameter) { @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); + if (request.getParameter("tags") == null) { + throw new MissingServletRequestParameterException("tags", "Tags"); + } + List tags = Arrays.stream(request.getParameter("tags").split(",")) .map(Tag::valueOf) .toList(); From 8e15fce993f4111bbb63f84c86d4e70bf3c7a91e Mon Sep 17 00:00:00 2001 From: Hanjaemo <110653660+Hanjaemo@users.noreply.github.com> Date: Thu, 13 Jun 2024 15:14:54 +0900 Subject: [PATCH 3/6] =?UTF-8?q?refactor:=20=EC=9A=94=EC=B2=AD=20=ED=8C=8C?= =?UTF-8?q?=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EB=88=84=EB=9D=BD=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EC=97=90=EB=9F=AC=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/contest/collectingbox/global/exception/ErrorCode.java | 2 +- .../collectingbox/global/exception/GlobalExceptionHandler.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/contest/collectingbox/global/exception/ErrorCode.java b/src/main/java/contest/collectingbox/global/exception/ErrorCode.java index 4034358..6f3841a 100644 --- a/src/main/java/contest/collectingbox/global/exception/ErrorCode.java +++ b/src/main/java/contest/collectingbox/global/exception/ErrorCode.java @@ -14,7 +14,7 @@ public enum ErrorCode { NOT_SELECTED_TAG(BAD_REQUEST, "수거함 태그는 반드시 한 개 이상 설정해야 합니다."), INVALID_REVIEW_CONTENT(BAD_REQUEST, "올바르지 않는 리뷰 내용입니다."), INVALID_BEAN(BAD_REQUEST, "유효하지 않은 데이터입니다."), - MISSING_REQUEST_PARAM(BAD_REQUEST, "필수 요청 파라미터가 존재하지 않습니다."), + MISSING_REQUEST_PARAM(BAD_REQUEST, "'%s' 타입의 '%s' 요청 파라미터가 존재하지 않습니다."), MISMATCH_REQUEST_PARAM(BAD_REQUEST, "요청 파라미터가 유효하지 않습니다."), // 404 diff --git a/src/main/java/contest/collectingbox/global/exception/GlobalExceptionHandler.java b/src/main/java/contest/collectingbox/global/exception/GlobalExceptionHandler.java index 2747ee7..c9af32e 100644 --- a/src/main/java/contest/collectingbox/global/exception/GlobalExceptionHandler.java +++ b/src/main/java/contest/collectingbox/global/exception/GlobalExceptionHandler.java @@ -30,7 +30,8 @@ public ApiResponse methodValidException(MethodArgumentNotValidException @ExceptionHandler(MissingServletRequestParameterException.class) @ResponseStatus(BAD_REQUEST) public ApiResponse handleMissingParams(MissingServletRequestParameterException e) { - return ApiResponse.error(MISSING_REQUEST_PARAM, MISSING_REQUEST_PARAM.getMessage()); + return ApiResponse.error(MISSING_REQUEST_PARAM, + String.format(MISSING_REQUEST_PARAM.getMessage(), e.getParameterType(), e.getParameterName())); } @ExceptionHandler(MethodArgumentTypeMismatchException.class) From 59dbf07cccbb72f39e2c599cf8df7444b11e971c Mon Sep 17 00:00:00 2001 From: Hanjaemo <110653660+Hanjaemo@users.noreply.github.com> Date: Thu, 13 Jun 2024 15:22:58 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20IllegalArgumentException=EC=97=90?= =?UTF-8?q?=20=EB=8C=80=ED=95=9C=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/config/web/TagsArgumentResolver.java | 12 ++++++++---- .../collectingbox/global/exception/ErrorCode.java | 1 + .../global/exception/GlobalExceptionHandler.java | 6 ++++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/main/java/contest/collectingbox/global/config/web/TagsArgumentResolver.java b/src/main/java/contest/collectingbox/global/config/web/TagsArgumentResolver.java index e3fabbb..0f987f6 100644 --- a/src/main/java/contest/collectingbox/global/config/web/TagsArgumentResolver.java +++ b/src/main/java/contest/collectingbox/global/config/web/TagsArgumentResolver.java @@ -27,9 +27,13 @@ public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer m throw new MissingServletRequestParameterException("tags", "Tags"); } - List tags = Arrays.stream(request.getParameter("tags").split(",")) - .map(Tag::valueOf) - .toList(); - return new Tags(tags); + try { + List tags = Arrays.stream(request.getParameter("tags").split(",")) + .map(Tag::valueOf) + .toList(); + return new Tags(tags); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("Invalid parameter value for tags"); + } } } diff --git a/src/main/java/contest/collectingbox/global/exception/ErrorCode.java b/src/main/java/contest/collectingbox/global/exception/ErrorCode.java index 6f3841a..39635ef 100644 --- a/src/main/java/contest/collectingbox/global/exception/ErrorCode.java +++ b/src/main/java/contest/collectingbox/global/exception/ErrorCode.java @@ -16,6 +16,7 @@ public enum ErrorCode { INVALID_BEAN(BAD_REQUEST, "유효하지 않은 데이터입니다."), MISSING_REQUEST_PARAM(BAD_REQUEST, "'%s' 타입의 '%s' 요청 파라미터가 존재하지 않습니다."), MISMATCH_REQUEST_PARAM(BAD_REQUEST, "요청 파라미터가 유효하지 않습니다."), + ILLEGAL_ARGUMENT(BAD_REQUEST, "유효하지 않은 값입니다."), // 404 NOT_FOUND_COLLECTING_BOX(NOT_FOUND, "해당 수거함이 존재하지 않습니다."), diff --git a/src/main/java/contest/collectingbox/global/exception/GlobalExceptionHandler.java b/src/main/java/contest/collectingbox/global/exception/GlobalExceptionHandler.java index c9af32e..31254db 100644 --- a/src/main/java/contest/collectingbox/global/exception/GlobalExceptionHandler.java +++ b/src/main/java/contest/collectingbox/global/exception/GlobalExceptionHandler.java @@ -39,4 +39,10 @@ public ApiResponse handleMissingParams(MissingServletRequestParameterExc public ApiResponse handleMissingParams(MethodArgumentTypeMismatchException e) { return ApiResponse.error(MISMATCH_REQUEST_PARAM, MISSING_REQUEST_PARAM.getMessage()); } + + @ExceptionHandler(IllegalArgumentException.class) + @ResponseStatus(BAD_REQUEST) + public ApiResponse handleIllegalArgument(IllegalArgumentException e) { + return ApiResponse.error(ILLEGAL_ARGUMENT, e.getMessage()); + } } From 49869d4d53aa5c67e1afb99586083b72435b9495 Mon Sep 17 00:00:00 2001 From: Hanjaemo <110653660+Hanjaemo@users.noreply.github.com> Date: Thu, 13 Jun 2024 15:24:47 +0900 Subject: [PATCH 5/6] =?UTF-8?q?refactor:=20=EC=A3=BC=EB=B3=80=20=EC=88=98?= =?UTF-8?q?=EA=B1=B0=ED=95=A8=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=EC=9D=98=20=EC=9A=94=EC=B2=AD=20?= =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=ED=83=80=EC=9E=85?= =?UTF-8?q?=EC=9D=84=20Point=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/web/PointArgumentResolver.java | 45 +++++++++++++++++++ .../application/CollectingBoxService.java | 5 +-- .../presentation/CollectingBoxController.java | 8 ++-- .../application/CollectingBoxServiceTest.java | 9 ++-- 4 files changed, 52 insertions(+), 15 deletions(-) create mode 100644 src/main/java/contest/collectingbox/global/config/web/PointArgumentResolver.java diff --git a/src/main/java/contest/collectingbox/global/config/web/PointArgumentResolver.java b/src/main/java/contest/collectingbox/global/config/web/PointArgumentResolver.java new file mode 100644 index 0000000..beb337c --- /dev/null +++ b/src/main/java/contest/collectingbox/global/config/web/PointArgumentResolver.java @@ -0,0 +1,45 @@ +package contest.collectingbox.global.config.web; + +import contest.collectingbox.global.exception.CollectingBoxException; +import contest.collectingbox.global.exception.ErrorCode; +import contest.collectingbox.global.utils.GeometryUtil; +import jakarta.servlet.http.HttpServletRequest; +import org.apache.coyote.BadRequestException; +import org.locationtech.jts.geom.Point; +import org.springframework.core.MethodParameter; +import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +public class PointArgumentResolver implements HandlerMethodArgumentResolver { + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.getParameterType().equals(Point.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { + HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); + + if (request.getParameter("latitude") == null) { + throw new MissingServletRequestParameterException("latitude", "Point"); + } + if (request.getParameter("longitude") == null) { + throw new MissingServletRequestParameterException("longitude", "Point"); + } + + double latitude; + double longitude; + + try { + latitude = Double.parseDouble(request.getParameter("latitude")); + longitude = Double.parseDouble(request.getParameter("longitude")); + return GeometryUtil.toPoint(longitude, latitude); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid parameter value for latitude or longitude"); + } + } +} diff --git a/src/main/java/contest/collectingbox/module/collectingbox/application/CollectingBoxService.java b/src/main/java/contest/collectingbox/module/collectingbox/application/CollectingBoxService.java index 947268e..025f252 100644 --- a/src/main/java/contest/collectingbox/module/collectingbox/application/CollectingBoxService.java +++ b/src/main/java/contest/collectingbox/module/collectingbox/application/CollectingBoxService.java @@ -1,6 +1,5 @@ package contest.collectingbox.module.collectingbox.application; -import contest.collectingbox.global.utils.GeometryUtil; import contest.collectingbox.module.collectingbox.domain.CollectingBox; import contest.collectingbox.module.collectingbox.domain.CollectingBoxRepository; import contest.collectingbox.module.collectingbox.domain.Tag; @@ -29,10 +28,8 @@ public class CollectingBoxService { private int radius; @Transactional(readOnly = true) - public List findCollectingBoxesWithinArea(final Double latitude, - final Double longitude, + public List findCollectingBoxesWithinArea(final Point center, final Tags tags) { - Point center = GeometryUtil.toPoint(longitude, latitude); return collectingBoxRepository.findAllWithinArea(center, radius, tags.toUnmodifiableList()) .stream() .map(CollectingBoxResponse::fromEntity) diff --git a/src/main/java/contest/collectingbox/module/collectingbox/presentation/CollectingBoxController.java b/src/main/java/contest/collectingbox/module/collectingbox/presentation/CollectingBoxController.java index e12ff90..2b2f79b 100644 --- a/src/main/java/contest/collectingbox/module/collectingbox/presentation/CollectingBoxController.java +++ b/src/main/java/contest/collectingbox/module/collectingbox/presentation/CollectingBoxController.java @@ -2,13 +2,12 @@ import contest.collectingbox.global.common.ApiResponse; import contest.collectingbox.module.collectingbox.application.CollectingBoxService; -import contest.collectingbox.module.collectingbox.domain.Tag; import contest.collectingbox.module.collectingbox.domain.Tags; import contest.collectingbox.module.collectingbox.dto.CollectingBoxDetailResponse; import contest.collectingbox.module.collectingbox.dto.CollectingBoxResponse; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.RequiredArgsConstructor; +import org.locationtech.jts.geom.Point; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -23,10 +22,9 @@ public class CollectingBoxController { @Operation(summary = "수거함 목록 조회", description = "위도와 경도를 기준으로 200m 반경에 위치한 수거함 목록을 조회합니다.") @GetMapping - public ApiResponse> findCollectingBoxesWithinArea(@RequestParam final Double latitude, - @RequestParam final Double longitude, + public ApiResponse> findCollectingBoxesWithinArea(final Point center, final Tags tags) { - return ApiResponse.ok(collectingBoxService.findCollectingBoxesWithinArea(latitude, longitude, tags)); + return ApiResponse.ok(collectingBoxService.findCollectingBoxesWithinArea(center, tags)); } @Operation(summary = "지역별 수거함 검색", description = "구/동 단위로 검색한 주소에 위치한 수거함 목록을 조회합니다.") diff --git a/src/test/java/contest/collectingbox/module/collectingbox/application/CollectingBoxServiceTest.java b/src/test/java/contest/collectingbox/module/collectingbox/application/CollectingBoxServiceTest.java index 3b268d0..f5e5ca5 100644 --- a/src/test/java/contest/collectingbox/module/collectingbox/application/CollectingBoxServiceTest.java +++ b/src/test/java/contest/collectingbox/module/collectingbox/application/CollectingBoxServiceTest.java @@ -32,9 +32,6 @@ @ExtendWith(MockitoExtension.class) class CollectingBoxServiceTest { - private final double LATITUDE = 37.4888953606578; - private final double LONGITUDE = 126.901185398046; - private Point center; @Value("${collecting-box.search.radius.meter}") @@ -48,7 +45,7 @@ class CollectingBoxServiceTest { @BeforeEach void setUp() { - center = GeometryUtil.toPoint(LONGITUDE, LATITUDE); + center = GeometryUtil.toPoint(126.901185398046, 37.4888953606578); } @Test @@ -68,7 +65,7 @@ void findCollectingBoxesWithinArea_Success_withinArea() { Collections.singletonList(box)); List result = - collectingBoxService.findCollectingBoxesWithinArea(LATITUDE, LONGITUDE, tags); + collectingBoxService.findCollectingBoxesWithinArea(center, tags); // then assertThat(result.get(0).getId()).isEqualTo(box.getId()); @@ -79,7 +76,7 @@ void findCollectingBoxesWithinArea_Success_withinArea() { void findCollectingBoxesWithinArea_Fail_ByTagIsEmpty() { // when, then Assertions.assertThatThrownBy( - () -> collectingBoxService.findCollectingBoxesWithinArea(LATITUDE, LONGITUDE, new Tags(List.of()))) + () -> collectingBoxService.findCollectingBoxesWithinArea(center, new Tags(List.of()))) .isInstanceOf(CollectingBoxException.class) .hasMessageContaining(ErrorCode.NOT_SELECTED_TAG.getMessage()); } From 5e47f03c03ab650cd683d377483f2c63dfeed8e2 Mon Sep 17 00:00:00 2001 From: Hanjaemo <110653660+Hanjaemo@users.noreply.github.com> Date: Thu, 13 Jun 2024 15:25:12 +0900 Subject: [PATCH 6/6] =?UTF-8?q?config:=20ArgumentResolver=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../collectingbox/global/config/WebConfig.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/contest/collectingbox/global/config/WebConfig.java b/src/main/java/contest/collectingbox/global/config/WebConfig.java index 8d18a0c..54f7df0 100644 --- a/src/main/java/contest/collectingbox/global/config/WebConfig.java +++ b/src/main/java/contest/collectingbox/global/config/WebConfig.java @@ -1,11 +1,17 @@ package contest.collectingbox.global.config; +import contest.collectingbox.global.config.web.PointArgumentResolver; +import contest.collectingbox.global.config.web.TagsArgumentResolver; import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import java.util.List; + @Configuration public class WebConfig implements WebMvcConfigurer { + @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") @@ -13,4 +19,10 @@ public void addCorsMappings(CorsRegistry registry) { .allowedMethods("*") .maxAge(3000); } + + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(new PointArgumentResolver()); + resolvers.add(new TagsArgumentResolver()); + } }