diff --git a/pyonsnalcolor-api/build.gradle b/pyonsnalcolor-api/build.gradle index 618e9db..8952b57 100644 --- a/pyonsnalcolor-api/build.gradle +++ b/pyonsnalcolor-api/build.gradle @@ -39,6 +39,8 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-batch:2.7.12' implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:3.1.7' testImplementation 'org.springframework.batch:spring-batch-test:4.3.8' + implementation 'org.springframework.boot:spring-boot-starter-aop' + implementation("net.gpedro.integrations.slack:slack-webhook:1.4.0") // FCM implementation 'com.google.firebase:firebase-admin:9.2.0' diff --git a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/aop/BatchExceptionAspect.java b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/aop/BatchExceptionAspect.java new file mode 100644 index 0000000..1db253b --- /dev/null +++ b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/aop/BatchExceptionAspect.java @@ -0,0 +1,76 @@ +package com.pyonsnalcolor.aop; + +import com.pyonsnalcolor.exception.PyonsnalcolorBatchException; +import lombok.extern.slf4j.Slf4j; +import net.gpedro.integrations.slack.SlackApi; +import net.gpedro.integrations.slack.SlackAttachment; +import net.gpedro.integrations.slack.SlackField; +import net.gpedro.integrations.slack.SlackMessage; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +@Slf4j +@Aspect +@Component +public class BatchExceptionAspect { + + @Value("${slack.url}") + private String SLACK_URL; + + @Pointcut("execution(* com.pyonsnalcolor.batch.service..*(..))") + private void allBatchService() {} + + @AfterThrowing(value = "allBatchService()", throwing = "exception") + public void catchBatchException(JoinPoint joinPoint, PyonsnalcolorBatchException exception) { + log.error("[{}] 배치 실행 중 {}에서 예외가 발생하였습니다.", exception.getClass().getSimpleName(), + joinPoint.getTarget().getClass().getSimpleName()); + log.error("[custom exception] {} {} ", exception.getErrorCode().name(), exception.getErrorCode().getMessage()); + log.error("[origin exception] {} {}", exception.getOriginException().getClass().getSimpleName(), + exception.getOriginException().getMessage()); + + sendErrorSlackAlarm(joinPoint, exception); + } + + private void sendErrorSlackAlarm(JoinPoint joinPoint, PyonsnalcolorBatchException exception) { + SlackApi api = new SlackApi(SLACK_URL); + + SlackMessage errorSlackMessage = createErrorSlackMessage(joinPoint, exception); + api.call(errorSlackMessage); + } + + private SlackMessage createErrorSlackMessage(JoinPoint joinPoint, PyonsnalcolorBatchException exception) { + SlackMessage slackMessage = new SlackMessage(); + slackMessage.setText("Batch Error Occur"); + slackMessage.setIcon(":beverage_box:"); + slackMessage.setUsername("pyonsnalcolor"); + + SlackAttachment slackAttachment = new SlackAttachment(); + slackAttachment.setFallback("Batch Error"); + slackAttachment.setTitle("배치 실행중 예외가 발생하였습니다."); + slackAttachment.setColor("#ffff00"); + slackAttachment.setText(Arrays.toString(exception.getStackTrace())); + slackAttachment.setFields ( + List.of( + new SlackField().setTitle("Occurred Time").setValue(LocalDateTime.now().toString()), + new SlackField().setTitle("Occurred Class") + .setValue(joinPoint.getTarget().getClass().getSimpleName()), + new SlackField().setTitle("Custom Message").setValue(exception.getErrorCode().getMessage()), + new SlackField().setTitle("Origin Exception") + .setValue(exception.getOriginException().getClass().getSimpleName()), + new SlackField().setTitle("Origin Exception Message") + .setValue(exception.getOriginException().getMessage()) + ) + ); + slackMessage.setAttachments(Collections.singletonList(slackAttachment)); + return slackMessage; + } +} \ No newline at end of file diff --git a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/cu/CuDescriptionBatch.java b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/cu/CuDescriptionBatch.java index bcdac13..59bdd6e 100644 --- a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/cu/CuDescriptionBatch.java +++ b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/cu/CuDescriptionBatch.java @@ -1,5 +1,6 @@ package com.pyonsnalcolor.batch.service.cu; +import com.pyonsnalcolor.exception.PyonsnalcolorBatchException; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; @@ -9,12 +10,15 @@ import java.io.IOException; import java.net.SocketTimeoutException; +import static com.pyonsnalcolor.exception.model.BatchErrorCode.*; +import static com.pyonsnalcolor.exception.model.BatchErrorCode.BATCH_UNAVAILABLE; + public interface CuDescriptionBatch { String CU_DESCRIPTION_PAGE_URL = "https://cu.bgfretail.com/product/view.do"; int TIMEOUT = 15000; - default String getDescription(Element element, String productType) throws Exception { + default String getDescription(Element element, String productType) { String productCode = getProductCode(element); try { @@ -28,11 +32,13 @@ default String getDescription(Element element, String productType) throws Except Elements elements = doc.select("ul.prodExplain li"); return elements.text(); } catch (IllegalArgumentException e) { - throw new IllegalArgumentException("URL 주소가 유효하지 않습니다."); + throw new PyonsnalcolorBatchException(INVALID_ACCESS, e); } catch (SocketTimeoutException e) { - throw new SocketTimeoutException("연결 시간이 초과하였습니다."); + throw new PyonsnalcolorBatchException(TIME_OUT, e); } catch (IOException e) { - throw new IOException("연결에 실패하였습니다."); + throw new PyonsnalcolorBatchException(IO_EXCEPTION, e); + } catch (Exception e) { + throw new PyonsnalcolorBatchException(BATCH_UNAVAILABLE, e); } } diff --git a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/cu/CuEventBatchService.java b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/cu/CuEventBatchService.java index b6ab165..2bb5ece 100644 --- a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/cu/CuEventBatchService.java +++ b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/cu/CuEventBatchService.java @@ -1,6 +1,7 @@ package com.pyonsnalcolor.batch.service.cu; import com.pyonsnalcolor.batch.service.EventBatchService; +import com.pyonsnalcolor.exception.PyonsnalcolorBatchException; import com.pyonsnalcolor.product.entity.BaseEventProduct; import com.pyonsnalcolor.product.enumtype.Category; import com.pyonsnalcolor.product.enumtype.EventType; @@ -15,11 +16,14 @@ import org.springframework.stereotype.Service; import org.springframework.web.util.UriComponentsBuilder; +import java.io.IOException; +import java.net.SocketTimeoutException; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import static com.pyonsnalcolor.exception.model.BatchErrorCode.*; import static com.pyonsnalcolor.product.entity.UUIDGenerator.generateId; @Service("CuEvent") @@ -40,10 +44,15 @@ protected List getAllProducts() { try { return getProducts(); + } catch (IllegalArgumentException e) { + throw new PyonsnalcolorBatchException(INVALID_ACCESS, e); + } catch (SocketTimeoutException e) { + throw new PyonsnalcolorBatchException(TIME_OUT, e); + } catch (IOException e) { + throw new PyonsnalcolorBatchException(IO_EXCEPTION, e); } catch (Exception e) { - log.error("CU 이벤트 상품 조회하는 데 실패했습니다.", e); + throw new PyonsnalcolorBatchException(BATCH_UNAVAILABLE, e); } - return null; // 이후에 에러 처리 관련 수정 - getAllProducts() 호출하는 쪽에 throw } private List getProducts() throws Exception { @@ -78,12 +87,7 @@ private BaseEventProduct convertToBaseEventProduct(Element element) { String eventTypeTag = element.select("div.badge").first().text(); EventType eventType = getCuEventType(eventTypeTag); - String description = null; - try { - description = getDescription(element, "event"); - } catch (Exception e) { - log.error("CU 이벤트 상품의 상세 정보를 조회할 수 없습니다.", e); - } + String description = getDescription(element, "event"); Category category = Category.matchCategoryByProductName(name); Tag tag = Tag.findTag(name); @@ -116,6 +120,7 @@ private EventType getCuEventType(String eventTypeTag) { if (eventTypeTag.equals("2+1")) { return EventType.TWO_TO_ONE; } - throw new IllegalArgumentException("CU 이벤트 타입을 찾을 수 없습니다."); + throw new PyonsnalcolorBatchException(INVALID_PRODUCT_TYPE, + new IllegalArgumentException("CU 이벤트 타입이 기존 엔티티와 다릅니다.")); } } \ No newline at end of file diff --git a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/cu/CuPbBatchService.java b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/cu/CuPbBatchService.java index 1044fd7..118a46c 100644 --- a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/cu/CuPbBatchService.java +++ b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/cu/CuPbBatchService.java @@ -1,6 +1,8 @@ package com.pyonsnalcolor.batch.service.cu; import com.pyonsnalcolor.batch.service.PbBatchService; +import com.pyonsnalcolor.exception.PyonsnalcolorBatchException; +import com.pyonsnalcolor.exception.model.BatchErrorCode; import com.pyonsnalcolor.product.entity.BasePbProduct; import com.pyonsnalcolor.product.enumtype.Category; import com.pyonsnalcolor.product.enumtype.StoreType; @@ -14,6 +16,8 @@ import org.springframework.stereotype.Service; import org.springframework.web.util.UriComponentsBuilder; +import java.io.IOException; +import java.net.SocketTimeoutException; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -37,13 +41,18 @@ public CuPbBatchService(PbProductRepository pbProductRepository) { } @Override - protected List getAllProducts(){ + protected List getAllProducts() { try { return getProductsByCategoryAll(); + } catch (IllegalArgumentException e) { + throw new PyonsnalcolorBatchException(BatchErrorCode.INVALID_ACCESS, e); + } catch (SocketTimeoutException e) { + throw new PyonsnalcolorBatchException(BatchErrorCode.TIME_OUT, e); + } catch (IOException e) { + throw new PyonsnalcolorBatchException(BatchErrorCode.IO_EXCEPTION, e); } catch (Exception e) { - log.error("CU PB 상품 조회하는 데 실패했습니다.", e); + throw new PyonsnalcolorBatchException(BatchErrorCode.BATCH_UNAVAILABLE, e); } - return null; // 이후에 에러 처리 관련 수정 - getAllProducts() 호출하는 쪽에 throw } private List getProductsByCategoryAll() throws Exception { @@ -82,12 +91,7 @@ private BasePbProduct convertToBasePbProduct(Element element) { image = SCHEMA + image; } String price = element.select("div.price > strong").first().text(); - String description = null; - try { - description = getDescription(element, "product"); - } catch (Exception e) { - log.error("CU PB 상품의 상세 정보를 조회할 수 없습니다.", e); - } + String description = getDescription(element, "product"); Category category = Category.matchCategoryByProductName(name); Tag tag = Tag.findTag(name); diff --git a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/emart24/Emart24EventBatchService.java b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/emart24/Emart24EventBatchService.java index 6489eb9..081f32c 100644 --- a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/emart24/Emart24EventBatchService.java +++ b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/emart24/Emart24EventBatchService.java @@ -64,7 +64,7 @@ private List parseProductsData(Elements productElements) { String giftImage = parseGiftImage(productElement); EventType eventType = parseEventType(productElement); String name = parseName(productElement); - String price = convertToNum(productElement.getElementsByClass("price").get(0).text()); + String price = productElement.getElementsByClass("price").get(0).text().split(" ")[0]; String originPrice = parseOriginPrice(productElement); String image = productElement.getElementsByTag("img").attr("src"); @@ -73,13 +73,6 @@ private List parseProductsData(Elements productElements) { return results; } - private String convertToNum(String price) { - String priceInfo = price.split(" ")[0]; - String result = priceInfo.replace(",", ""); - - return result; - } - private String parseGiftImage(Element productElement) { Elements giftElement = productElement.select("div.dumgift"); String giftImage = NOT_EXIST; @@ -97,7 +90,8 @@ private String parseOriginPrice(Element productElement) { originPrice = originPriceElement.get(0).text(); } - return originPrice; + String parsedOriginPrice = originPrice.split(" ")[0]; + return parsedOriginPrice; } private String parseName(Element productElement) { diff --git a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/emart24/Emart24PbBatchService.java b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/emart24/Emart24PbBatchService.java index 1da5d8e..7161fd7 100644 --- a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/emart24/Emart24PbBatchService.java +++ b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/emart24/Emart24PbBatchService.java @@ -62,7 +62,7 @@ private List parseProductsData(Elements productElements) { Elements itemTitle = productElement.getElementsByClass("itemtitle"); Element element = itemTitle.get(0); String name = element.getElementsByTag("a").get(0).text(); - String price = convertToNum(productElement.getElementsByClass("price").get(0).text()); + String price = productElement.getElementsByClass("price").get(0).text().split(" ")[0]; String image = productElement.getElementsByTag("img").attr("src"); results.add(convertToBasePbProduct(image, name, price)); @@ -70,13 +70,6 @@ private List parseProductsData(Elements productElements) { return results; } - private String convertToNum(String price) { - String priceInfo = price.split(" ")[0]; - String result = priceInfo.replace(",", ""); - - return result; - } - private BasePbProduct convertToBasePbProduct(String image, String name, String price) { Category category = Category.matchCategoryByProductName(name); Tag tag = Tag.findTag(name); diff --git a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/gs25/GS25EventBatchService.java b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/gs25/GS25EventBatchService.java index 5a433c8..cad63b1 100644 --- a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/gs25/GS25EventBatchService.java +++ b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/gs25/GS25EventBatchService.java @@ -20,6 +20,7 @@ import org.springframework.stereotype.Service; import java.io.IOException; +import java.text.NumberFormat; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -100,7 +101,9 @@ private BaseEventProduct convertToBaseEventProduct(Object product) { Map productMap = objectMapper.convertValue(product, Map.class); String image = (String) productMap.get("attFileNm"); String name = (String) productMap.get("goodsNm"); - String price = Double.toString((Double) productMap.get("price")); + String price = Double.toString((Double) productMap.get("price")).split("\\.")[0]; + int priceInt = Integer.parseInt(price); + String formattedPrice = NumberFormat.getInstance().format(priceInt); String eventType = (String) ((Map) productMap.get("eventTypeSp")).get("code"); String giftImage = (String) productMap.get("giftAttFileNm"); Category category = Category.matchCategoryByProductName(name); @@ -114,7 +117,7 @@ private BaseEventProduct convertToBaseEventProduct(Object product) { .id(generateId()) .giftImage(giftImage) .image(image) - .price(price) + .price(formattedPrice) .name(name) .category(category) .tag(tag) diff --git a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/gs25/GS25PbBatchService.java b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/gs25/GS25PbBatchService.java index 760f054..b0fbf68 100644 --- a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/gs25/GS25PbBatchService.java +++ b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/gs25/GS25PbBatchService.java @@ -19,6 +19,7 @@ import org.springframework.stereotype.Service; import java.io.IOException; +import java.text.NumberFormat; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -91,14 +92,17 @@ private BasePbProduct convertToBasePbProduct(Object product) { Map productMap = objectMapper.convertValue(product, Map.class); String image = (String) productMap.get("attFileNm"); String name = (String) productMap.get("goodsNm"); - String price = Double.toString((Double) productMap.get("price")); + String price = Double.toString((Double) productMap.get("price")).split("\\.")[0];; + int priceInt = Integer.parseInt(price); + String formattedPrice = NumberFormat.getInstance().format(priceInt); + Category category = Category.matchCategoryByProductName(name); Tag tag = Tag.findTag(name); BasePbProduct basePbProduct = BasePbProduct.builder() .id(generateId()) .name(name) - .price(price) + .price(formattedPrice) .storeType(StoreType.GS25) .updatedTime(LocalDateTime.now()) .image(image) diff --git a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/seven/SevenEventBatchService.java b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/seven/SevenEventBatchService.java index e0eb926..265f405 100644 --- a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/seven/SevenEventBatchService.java +++ b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/seven/SevenEventBatchService.java @@ -1,6 +1,7 @@ package com.pyonsnalcolor.batch.service.seven; import com.pyonsnalcolor.batch.service.EventBatchService; +import com.pyonsnalcolor.exception.PyonsnalcolorBatchException; import com.pyonsnalcolor.product.entity.BaseEventProduct; import com.pyonsnalcolor.product.repository.EventProductRepository; import lombok.extern.slf4j.Slf4j; @@ -11,11 +12,15 @@ import org.springframework.web.util.UriComponentsBuilder; import java.io.IOException; +import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; +import static com.pyonsnalcolor.exception.model.BatchErrorCode.*; +import static com.pyonsnalcolor.exception.model.BatchErrorCode.BATCH_UNAVAILABLE; + @Service("SevenEvent") @Slf4j public class SevenEventBatchService extends EventBatchService { @@ -42,10 +47,15 @@ protected List getAllProducts() { private List getProductsAllTab(SevenEventTab sevenEventTab) { try { return getProductsByTab(sevenEventTab); - } catch (IOException ioException) { - log.error("세븐일레븐 이벤트 {}탭의 상품 조회하는 데 실패했습니다.", sevenEventTab, ioException); + } catch (IllegalArgumentException e) { + throw new PyonsnalcolorBatchException(INVALID_ACCESS, e); + } catch (SocketTimeoutException e) { + throw new PyonsnalcolorBatchException(TIME_OUT, e); + } catch (IOException e) { + throw new PyonsnalcolorBatchException(IO_EXCEPTION, e); + } catch (Exception e) { + throw new PyonsnalcolorBatchException(BATCH_UNAVAILABLE, e); } - return null; } public List getProductsByTab(SevenEventTab sevenEventTab) throws IOException { diff --git a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/seven/SevenEventTab.java b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/seven/SevenEventTab.java index 812cb96..f95e0db 100644 --- a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/seven/SevenEventTab.java +++ b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/seven/SevenEventTab.java @@ -1,5 +1,7 @@ package com.pyonsnalcolor.batch.service.seven; +import com.pyonsnalcolor.exception.PyonsnalcolorBatchException; +import com.pyonsnalcolor.exception.model.BatchErrorCode; import com.pyonsnalcolor.product.entity.BaseEventProduct; import com.pyonsnalcolor.product.enumtype.Category; import com.pyonsnalcolor.product.enumtype.EventType; @@ -13,12 +15,15 @@ import org.jsoup.select.Elements; import org.springframework.web.util.UriComponentsBuilder; +import java.io.IOException; +import java.net.SocketTimeoutException; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; +import static com.pyonsnalcolor.exception.model.BatchErrorCode.*; import static com.pyonsnalcolor.product.entity.UUIDGenerator.generateId; @Slf4j @@ -137,9 +142,14 @@ private String getOriginPrice(String originProductCode) { Document doc = Jsoup.connect(originPriceUrl).timeout(TIMEOUT).get(); Elements elements = doc.select("div.cont_top span.product_price del"); return elements.text().replace(" >", ""); + } catch (IllegalArgumentException e) { + throw new PyonsnalcolorBatchException(INVALID_ACCESS, e); + } catch (SocketTimeoutException e) { + throw new PyonsnalcolorBatchException(TIME_OUT, e); + } catch (IOException e) { + throw new PyonsnalcolorBatchException(IO_EXCEPTION, e); } catch (Exception e) { - log.error("세븐일레븐 할인 상품의 상세 페이지로 이동할 수 없습니다.", e); + throw new PyonsnalcolorBatchException(BATCH_UNAVAILABLE, e); } - return null; } } \ No newline at end of file diff --git a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/seven/SevenPbBatchService.java b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/seven/SevenPbBatchService.java index fa48b96..96808c3 100644 --- a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/seven/SevenPbBatchService.java +++ b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/batch/service/seven/SevenPbBatchService.java @@ -1,6 +1,8 @@ package com.pyonsnalcolor.batch.service.seven; import com.pyonsnalcolor.batch.service.PbBatchService; +import com.pyonsnalcolor.exception.PyonsnalcolorBatchException; +import com.pyonsnalcolor.exception.model.BatchErrorCode; import com.pyonsnalcolor.product.entity.BasePbProduct; import com.pyonsnalcolor.product.enumtype.Category; import com.pyonsnalcolor.product.enumtype.StoreType; @@ -15,11 +17,14 @@ import org.springframework.web.util.UriComponentsBuilder; import java.io.IOException; +import java.net.SocketTimeoutException; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import static com.pyonsnalcolor.exception.model.BatchErrorCode.*; +import static com.pyonsnalcolor.exception.model.BatchErrorCode.BATCH_UNAVAILABLE; import static com.pyonsnalcolor.product.entity.UUIDGenerator.generateId; @Service("SevenPb") @@ -37,13 +42,18 @@ public SevenPbBatchService(PbProductRepository pbProductRepository) { } @Override - protected List getAllProducts() { + protected List getAllProducts(){ try { return getProducts(); + } catch (IllegalArgumentException e) { + throw new PyonsnalcolorBatchException(INVALID_ACCESS, e); + } catch (SocketTimeoutException e) { + throw new PyonsnalcolorBatchException(TIME_OUT, e); + } catch (IOException e) { + throw new PyonsnalcolorBatchException(IO_EXCEPTION, e); } catch (Exception e) { - log.error("세븐일레븐 PB 상품 조회하는 데 실패했습니다.", e); + throw new PyonsnalcolorBatchException(BATCH_UNAVAILABLE, e); } - return null; // 이후에 에러 처리 관련 수정 - getAllProducts() 호출하는 쪽에 throw } private List getProducts() throws IOException { diff --git a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/exception/PyonsnalcolorBatchException.java b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/exception/PyonsnalcolorBatchException.java new file mode 100644 index 0000000..9cd002c --- /dev/null +++ b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/exception/PyonsnalcolorBatchException.java @@ -0,0 +1,15 @@ +package com.pyonsnalcolor.exception; + +import com.pyonsnalcolor.exception.model.ErrorCode; +import lombok.Getter; + +@Getter +public class PyonsnalcolorBatchException extends PyonsnalcolorException { + + private final Exception originException; + + public PyonsnalcolorBatchException(ErrorCode errorCode, Exception originException) { + super(errorCode); + this.originException = originException; + } +} \ No newline at end of file diff --git a/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/exception/model/BatchErrorCode.java b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/exception/model/BatchErrorCode.java new file mode 100644 index 0000000..1d6533c --- /dev/null +++ b/pyonsnalcolor-api/src/main/java/com/pyonsnalcolor/exception/model/BatchErrorCode.java @@ -0,0 +1,21 @@ +package com.pyonsnalcolor.exception.model; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; + +@Getter +@RequiredArgsConstructor +public enum BatchErrorCode implements ErrorCode{ + + INVALID_ACCESS(BAD_REQUEST, "해당 URL이 유효하지 않습니다."), + TIME_OUT(BAD_REQUEST, "연결 시간이 초과되었습니다."), + IO_EXCEPTION(BAD_REQUEST, "페이지에 접근할 수 없습니다."), + BATCH_UNAVAILABLE(BAD_REQUEST, "배치를 실행할 수 없습니다. 확인이 필요합니다."), + INVALID_PRODUCT_TYPE(BAD_REQUEST, "상품 정보가 기존 형식과 다릅니다."); + + private final HttpStatus httpStatus; + private final String message; +} \ No newline at end of file diff --git a/pyonsnalcolor-api/src/main/resources/application.yml b/pyonsnalcolor-api/src/main/resources/application.yml index 512f771..89f0738 100644 --- a/pyonsnalcolor-api/src/main/resources/application.yml +++ b/pyonsnalcolor-api/src/main/resources/application.yml @@ -54,4 +54,6 @@ springdoc: try-it-out-enabled: false fcm: key: ${FCM_KEY} - scope: https://www.googleapis.com/auth/firebase.messaging \ No newline at end of file + scope: https://www.googleapis.com/auth/firebase.messaging +slack: + url: ${SLACK_URL} \ No newline at end of file