From f0fcbb588d18e864a7cc5eb867ea86c0db7c7034 Mon Sep 17 00:00:00 2001 From: bedroomghost Date: Tue, 15 Apr 2025 20:54:44 +0200 Subject: [PATCH] feat: Added exception handling for rest-api --- .../exceptions/NotFoundException.java | 8 ++++++ .../application/services/PriceService.java | 6 ++++- .../adapters/PriceControllerAdapter.java | 13 +++------ .../handlers/AdapterExceptionHandler.java | 27 +++++++++++++++++++ .../model/mappers/PriceResponseMapper.java | 18 +++++++++++++ 5 files changed, 61 insertions(+), 11 deletions(-) create mode 100644 application/src/main/java/com/techivw/webprice/application/exceptions/NotFoundException.java create mode 100644 infrastructure/in/rest-api/src/main/java/com/techivw/webprice/infrastructure/in/controllers/handlers/AdapterExceptionHandler.java create mode 100644 infrastructure/in/rest-api/src/main/java/com/techivw/webprice/infrastructure/in/controllers/model/mappers/PriceResponseMapper.java diff --git a/application/src/main/java/com/techivw/webprice/application/exceptions/NotFoundException.java b/application/src/main/java/com/techivw/webprice/application/exceptions/NotFoundException.java new file mode 100644 index 0000000..d3b2145 --- /dev/null +++ b/application/src/main/java/com/techivw/webprice/application/exceptions/NotFoundException.java @@ -0,0 +1,8 @@ +package com.techivw.webprice.application.exceptions; + +public class NotFoundException extends RuntimeException { + + public NotFoundException(String message) { + super(message); + } +} diff --git a/application/src/main/java/com/techivw/webprice/application/services/PriceService.java b/application/src/main/java/com/techivw/webprice/application/services/PriceService.java index 247c416..eee1d41 100644 --- a/application/src/main/java/com/techivw/webprice/application/services/PriceService.java +++ b/application/src/main/java/com/techivw/webprice/application/services/PriceService.java @@ -1,5 +1,6 @@ package com.techivw.webprice.application.services; +import com.techivw.webprice.application.exceptions.NotFoundException; import com.techivw.webprice.application.ports.in.PriceServicePort; import com.techivw.webprice.application.ports.out.PriceRepositoryPort; import com.techivw.webprice.domain.Price; @@ -16,6 +17,9 @@ public class PriceService implements PriceServicePort { @Override public Price getPriceWithHighestPriorityByDateTimeAndProductIdAndBrandId(LocalDateTime dateTime, Long productId, Long brandId) { - return priceRepositoryPort.findHighestPriorityPriceByDateTimeAndProductIdAndBrandId(dateTime, productId, brandId).orElse(null); + return priceRepositoryPort.findHighestPriorityPriceByDateTimeAndProductIdAndBrandId(dateTime, productId, brandId) + .orElseThrow(() -> + new NotFoundException(String.format( + "Price for product %d of brand %d not found for date %s", productId, brandId, dateTime))); } } diff --git a/infrastructure/in/rest-api/src/main/java/com/techivw/webprice/infrastructure/in/controllers/adapters/PriceControllerAdapter.java b/infrastructure/in/rest-api/src/main/java/com/techivw/webprice/infrastructure/in/controllers/adapters/PriceControllerAdapter.java index cdb1c0f..f790640 100644 --- a/infrastructure/in/rest-api/src/main/java/com/techivw/webprice/infrastructure/in/controllers/adapters/PriceControllerAdapter.java +++ b/infrastructure/in/rest-api/src/main/java/com/techivw/webprice/infrastructure/in/controllers/adapters/PriceControllerAdapter.java @@ -3,6 +3,7 @@ package com.techivw.webprice.infrastructure.in.controllers.adapters; import com.techivw.webprice.application.ports.in.PriceServicePort; import com.techivw.webprice.domain.Price; import com.techivw.webprice.infrastructure.in.controllers.model.PriceResponse; +import com.techivw.webprice.infrastructure.in.controllers.model.mappers.PriceResponseMapper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; @@ -35,8 +36,8 @@ public class PriceControllerAdapter { description = "Price information found", content = @Content(mediaType = "application/json", schema = @Schema(implementation = PriceResponse.class)) ) - @ApiResponse(responseCode = "404", description = "Price information not found for the given parameters") @ApiResponse(responseCode = "400", description = "Invalid request parameters") + @ApiResponse(responseCode = "404", description = "Price information not found for the given parameters") public ResponseEntity getPrice( @Parameter(description = "Date and time for price lookup (ISO format)", example = "2025-04-30T12:00:00") @RequestParam(name = "dateTime") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime dateTime, @@ -46,14 +47,6 @@ public class PriceControllerAdapter { @RequestParam(name = "brandId") Long brandId) { Price price = priceServicePort.getPriceWithHighestPriorityByDateTimeAndProductIdAndBrandId(dateTime, productId, brandId); - PriceResponse priceResponse = PriceResponse.builder() - .productId(price.getProductId()) - .brandId(price.getBrandId()) - .priceList(price.getPriceList()) - .startDate(price.getStartDate()) - .endDate(price.getEndDate()) - .price(price.getPrice()) - .build(); - return ResponseEntity.ok(priceResponse); + return ResponseEntity.ok(PriceResponseMapper.fromPrice(price)); } } diff --git a/infrastructure/in/rest-api/src/main/java/com/techivw/webprice/infrastructure/in/controllers/handlers/AdapterExceptionHandler.java b/infrastructure/in/rest-api/src/main/java/com/techivw/webprice/infrastructure/in/controllers/handlers/AdapterExceptionHandler.java new file mode 100644 index 0000000..50b1daa --- /dev/null +++ b/infrastructure/in/rest-api/src/main/java/com/techivw/webprice/infrastructure/in/controllers/handlers/AdapterExceptionHandler.java @@ -0,0 +1,27 @@ +package com.techivw.webprice.infrastructure.in.controllers.handlers; + +import com.techivw.webprice.application.exceptions.NotFoundException; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import static org.springframework.http.HttpStatus.NOT_FOUND; + +@RestControllerAdvice +public class AdapterExceptionHandler { + + @ExceptionHandler(NotFoundException.class) + public ResponseEntity> handleNotFoundException(NotFoundException ex) { + Map body = new HashMap<>(); + body.put("timestamp", new Date()); + body.put("status", NOT_FOUND.value()); + body.put("error", "Not Found"); + body.put("message", ex.getMessage()); + + return new ResponseEntity<>(body, NOT_FOUND); + } +} diff --git a/infrastructure/in/rest-api/src/main/java/com/techivw/webprice/infrastructure/in/controllers/model/mappers/PriceResponseMapper.java b/infrastructure/in/rest-api/src/main/java/com/techivw/webprice/infrastructure/in/controllers/model/mappers/PriceResponseMapper.java new file mode 100644 index 0000000..e938b07 --- /dev/null +++ b/infrastructure/in/rest-api/src/main/java/com/techivw/webprice/infrastructure/in/controllers/model/mappers/PriceResponseMapper.java @@ -0,0 +1,18 @@ +package com.techivw.webprice.infrastructure.in.controllers.model.mappers; + +import com.techivw.webprice.domain.Price; +import com.techivw.webprice.infrastructure.in.controllers.model.PriceResponse; + +public class PriceResponseMapper { + + public static PriceResponse fromPrice(Price price) { + return PriceResponse.builder() + .productId(price.getProductId()) + .brandId(price.getBrandId()) + .priceList(price.getPriceList()) + .startDate(price.getStartDate()) + .endDate(price.getEndDate()) + .price(price.getPrice()) + .build(); + } +}