feat: Added exception handling for rest-api

This commit is contained in:
bedroomghost 2025-04-15 20:54:44 +02:00
parent 8dc84d2110
commit f0fcbb588d
5 changed files with 61 additions and 11 deletions

View File

@ -0,0 +1,8 @@
package com.techivw.webprice.application.exceptions;
public class NotFoundException extends RuntimeException {
public NotFoundException(String message) {
super(message);
}
}

View File

@ -1,5 +1,6 @@
package com.techivw.webprice.application.services; 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.in.PriceServicePort;
import com.techivw.webprice.application.ports.out.PriceRepositoryPort; import com.techivw.webprice.application.ports.out.PriceRepositoryPort;
import com.techivw.webprice.domain.Price; import com.techivw.webprice.domain.Price;
@ -16,6 +17,9 @@ public class PriceService implements PriceServicePort {
@Override @Override
public Price getPriceWithHighestPriorityByDateTimeAndProductIdAndBrandId(LocalDateTime dateTime, Long productId, Long brandId) { 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)));
} }
} }

View File

@ -3,6 +3,7 @@ package com.techivw.webprice.infrastructure.in.controllers.adapters;
import com.techivw.webprice.application.ports.in.PriceServicePort; import com.techivw.webprice.application.ports.in.PriceServicePort;
import com.techivw.webprice.domain.Price; import com.techivw.webprice.domain.Price;
import com.techivw.webprice.infrastructure.in.controllers.model.PriceResponse; 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.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Content;
@ -35,8 +36,8 @@ public class PriceControllerAdapter {
description = "Price information found", description = "Price information found",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = PriceResponse.class)) 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 = "400", description = "Invalid request parameters")
@ApiResponse(responseCode = "404", description = "Price information not found for the given parameters")
public ResponseEntity<PriceResponse> getPrice( public ResponseEntity<PriceResponse> getPrice(
@Parameter(description = "Date and time for price lookup (ISO format)", example = "2025-04-30T12:00:00") @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, @RequestParam(name = "dateTime") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime dateTime,
@ -46,14 +47,6 @@ public class PriceControllerAdapter {
@RequestParam(name = "brandId") Long brandId) { @RequestParam(name = "brandId") Long brandId) {
Price price = priceServicePort.getPriceWithHighestPriorityByDateTimeAndProductIdAndBrandId(dateTime, productId, brandId); Price price = priceServicePort.getPriceWithHighestPriorityByDateTimeAndProductIdAndBrandId(dateTime, productId, brandId);
PriceResponse priceResponse = PriceResponse.builder() return ResponseEntity.ok(PriceResponseMapper.fromPrice(price));
.productId(price.getProductId())
.brandId(price.getBrandId())
.priceList(price.getPriceList())
.startDate(price.getStartDate())
.endDate(price.getEndDate())
.price(price.getPrice())
.build();
return ResponseEntity.ok(priceResponse);
} }
} }

View File

@ -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<Map<String, Object>> handleNotFoundException(NotFoundException ex) {
Map<String, Object> 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);
}
}

View File

@ -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();
}
}