diff --git a/catalog-service/src/main/java/com/example/catalogservice/entities/Product.java b/catalog-service/src/main/java/com/example/catalogservice/entities/Product.java index 7a0eb1ac..b8d6dec1 100644 --- a/catalog-service/src/main/java/com/example/catalogservice/entities/Product.java +++ b/catalog-service/src/main/java/com/example/catalogservice/entities/Product.java @@ -18,7 +18,7 @@ public class Product implements Serializable { @Id private Long id; - private String code; + private String productCode; private String productName; @@ -39,12 +39,12 @@ public Product setId(Long id) { return this; } - public String getCode() { - return code; + public String getProductCode() { + return productCode; } - public Product setCode(String code) { - this.code = code; + public Product setProductCode(String productCode) { + this.productCode = productCode; return this; } diff --git a/catalog-service/src/main/java/com/example/catalogservice/mapper/ProductMapper.java b/catalog-service/src/main/java/com/example/catalogservice/mapper/ProductMapper.java index a5818092..29ef6d74 100644 --- a/catalog-service/src/main/java/com/example/catalogservice/mapper/ProductMapper.java +++ b/catalog-service/src/main/java/com/example/catalogservice/mapper/ProductMapper.java @@ -24,6 +24,7 @@ public interface ProductMapper { @Mapping(target = "id", ignore = true) Product toEntity(ProductRequest productRequest); + @Mapping(target = "code", source = "productCode") ProductDto toProductDto(ProductRequest productRequest); @Mapping(target = "id", ignore = true) diff --git a/catalog-service/src/main/java/com/example/catalogservice/model/request/ProductRequest.java b/catalog-service/src/main/java/com/example/catalogservice/model/request/ProductRequest.java index f23aca27..bf30a883 100644 --- a/catalog-service/src/main/java/com/example/catalogservice/model/request/ProductRequest.java +++ b/catalog-service/src/main/java/com/example/catalogservice/model/request/ProductRequest.java @@ -10,7 +10,7 @@ Licensed under MIT License Copyright (c) 2021-2023 Raja Kolli. import jakarta.validation.constraints.Positive; public record ProductRequest( - @NotBlank(message = "Product code can't be blank") String code, + @NotBlank(message = "Product code can't be blank") String productCode, String productName, String description, String imageUrl, diff --git a/catalog-service/src/main/java/com/example/catalogservice/model/response/ProductResponse.java b/catalog-service/src/main/java/com/example/catalogservice/model/response/ProductResponse.java index 90f86eb8..de1462e0 100644 --- a/catalog-service/src/main/java/com/example/catalogservice/model/response/ProductResponse.java +++ b/catalog-service/src/main/java/com/example/catalogservice/model/response/ProductResponse.java @@ -11,7 +11,7 @@ Licensed under MIT License Copyright (c) 2023-2024 Raja Kolli. public record ProductResponse( Long id, - String code, + String productCode, String productName, String description, String imageUrl, @@ -24,7 +24,7 @@ public ProductResponse withInStock(final boolean inStock) { ? this : new ProductResponse( this.id, - this.code, + this.productCode, this.productName, this.description, this.imageUrl, diff --git a/catalog-service/src/main/java/com/example/catalogservice/repositories/ProductRepository.java b/catalog-service/src/main/java/com/example/catalogservice/repositories/ProductRepository.java index a4904669..d34d2b91 100644 --- a/catalog-service/src/main/java/com/example/catalogservice/repositories/ProductRepository.java +++ b/catalog-service/src/main/java/com/example/catalogservice/repositories/ProductRepository.java @@ -17,9 +17,9 @@ Licensed under MIT License Copyright (c) 2021-2023 Raja Kolli. public interface ProductRepository extends ReactiveCrudRepository, ReactiveSortingRepository { - Mono countDistinctByCodeAllIgnoreCaseIn(List code); + Mono countDistinctByProductCodeAllIgnoreCaseIn(List productCodeList); - Mono findByCodeAllIgnoreCase(String code); + Mono findByProductCodeAllIgnoreCase(String productCode); Flux findAllBy(Pageable pageable); } diff --git a/catalog-service/src/main/java/com/example/catalogservice/services/ProductService.java b/catalog-service/src/main/java/com/example/catalogservice/services/ProductService.java index 7912191c..0a923d13 100644 --- a/catalog-service/src/main/java/com/example/catalogservice/services/ProductService.java +++ b/catalog-service/src/main/java/com/example/catalogservice/services/ProductService.java @@ -92,7 +92,7 @@ public Mono> findAllProducts( List productCodeList = productResponseList.stream() - .map(ProductResponse::code) + .map(ProductResponse::productCode) .toList(); return getInventoryByProductCodes(productCodeList) @@ -118,7 +118,7 @@ private List updateProductAvailability( .map( productResponse -> { int availableQuantity = - inventoriesMap.getOrDefault(productResponse.code(), 0); + inventoriesMap.getOrDefault(productResponse.productCode(), 0); return productResponse.withInStock(availableQuantity > 0); }) .toList(); @@ -136,7 +136,7 @@ public Mono findProductById(Long id) { .map(productMapper::toProductResponse) .flatMap( productResponse -> - getInventoryByProductCode(productResponse.code()) + getInventoryByProductCode(productResponse.productCode()) .map( inventoryDto -> productResponse.withInStock( @@ -153,7 +153,7 @@ public Mono findProductByProductCode( String productCode, boolean fetchInStock) { Mono productResponseMono = productRepository - .findByCodeAllIgnoreCase(productCode) + .findByProductCodeAllIgnoreCase(productCode) .map(productMapper::toProductResponse) .switchIfEmpty(Mono.error(new ProductNotFoundException(productCode))); @@ -165,7 +165,7 @@ public Mono findProductByProductCode( private Mono fetchInventoryAndUpdateProductResponse( ProductResponse productResponse) { - return getInventoryByProductCode(productResponse.code()) + return getInventoryByProductCode(productResponse.productCode()) .map( inventoryResponse -> productResponse.withInStock( @@ -191,7 +191,8 @@ public Mono saveProduct(ProductRequest productRequest) { e -> // Handle unique key constraint violation here Mono.error( - new ProductAlreadyExistsException(productRequest.code()))) + new ProductAlreadyExistsException( + productRequest.productCode()))) .map(productMapper::toProductResponse); } @@ -204,7 +205,7 @@ public Mono deleteProductById(Long id) { public Mono productExistsByProductCodes(List productCodes) { log.info("checking if products Exists :{}", productCodes); return productRepository - .countDistinctByCodeAllIgnoreCaseIn(productCodes) + .countDistinctByProductCodeAllIgnoreCaseIn(productCodes) .map(count -> count == productCodes.size()); } diff --git a/catalog-service/src/main/resources/db/changelog/migration/01-create-product-table.yaml b/catalog-service/src/main/resources/db/changelog/migration/01-create-product-table.yaml index e5b6c2e7..be94486b 100644 --- a/catalog-service/src/main/resources/db/changelog/migration/01-create-product-table.yaml +++ b/catalog-service/src/main/resources/db/changelog/migration/01-create-product-table.yaml @@ -36,7 +36,7 @@ databaseChangeLog: - column: constraints: nullable: 'false' - name: code + name: product_code type: ${string.type} - column: constraints: @@ -54,6 +54,6 @@ databaseChangeLog: type: 'NUMERIC(19,2)' tableName: products addUniqueConstraint: - columnNames: code - constraintName: uc_products_code + columnNames: product_code + constraintName: uc_product_code tableName: products diff --git a/catalog-service/src/test/java/com/example/catalogservice/services/ProductServiceTest.java b/catalog-service/src/test/java/com/example/catalogservice/services/ProductServiceTest.java index 96e2ff75..085982f1 100644 --- a/catalog-service/src/test/java/com/example/catalogservice/services/ProductServiceTest.java +++ b/catalog-service/src/test/java/com/example/catalogservice/services/ProductServiceTest.java @@ -55,7 +55,7 @@ void testGenerateProducts() { int randomPrice = ThreadLocalRandom.current().nextInt(1, 101); return new Product() .setId(1L) - .setCode(request.code()) + .setProductCode(request.productCode()) .setProductName(request.productName()) .setDescription(request.description()) .setPrice(randomPrice); @@ -68,7 +68,7 @@ void testGenerateProducts() { ProductRequest request = invocation.getArgument(0); int randomPrice = ThreadLocalRandom.current().nextInt(1, 101); return new ProductDto( - request.code(), + request.productCode(), request.productName(), request.description(), (double) randomPrice); @@ -81,7 +81,7 @@ void testGenerateProducts() { Product product = invocationOnMock.getArgument(0); return new ProductResponse( product.getId(), - product.getCode(), + product.getProductCode(), product.getProductName(), product.getDescription(), null, diff --git a/catalog-service/src/test/java/com/example/catalogservice/web/controllers/ProductControllerIT.java b/catalog-service/src/test/java/com/example/catalogservice/web/controllers/ProductControllerIT.java index 56f24384..0b2dbb3c 100644 --- a/catalog-service/src/test/java/com/example/catalogservice/web/controllers/ProductControllerIT.java +++ b/catalog-service/src/test/java/com/example/catalogservice/web/controllers/ProductControllerIT.java @@ -69,17 +69,17 @@ void setUp() { List productList = List.of( new Product() - .setCode("P001") + .setProductCode("P001") .setProductName("name 1") .setDescription("description 1") .setPrice(9.0), new Product() - .setCode("P002") + .setProductCode("P002") .setProductName("name 2") .setDescription("description 2") .setPrice(10.0), new Product() - .setCode("P003") + .setProductCode("P003") .setProductName("name 3") .setDescription("description 3") .setPrice(11.0)); @@ -213,7 +213,9 @@ void shouldFindProductById() throws JsonProcessingException { Product product = savedProductList.getFirst(); Long productId = product.getId(); mockBackendEndpoint( - 200, objectMapper.writeValueAsString(new InventoryResponse(product.getCode(), 0))); + 200, + objectMapper.writeValueAsString( + new InventoryResponse(product.getProductCode(), 0))); webTestClient .get() .uri("/api/catalog/id/{id}", productId) @@ -225,8 +227,8 @@ void shouldFindProductById() throws JsonProcessingException { .expectBody() .jsonPath("$.id") .isEqualTo(product.getId()) - .jsonPath("$.code") - .isEqualTo(product.getCode()) + .jsonPath("$.productCode") + .isEqualTo(product.getProductCode()) .jsonPath("$.productName") .isEqualTo(product.getProductName()) .jsonPath("$.description") @@ -256,7 +258,9 @@ void shouldRetryOnErrorAndFetchSuccessResponse() throws JsonProcessingException Product product = savedProductList.getFirst(); Long productId = product.getId(); mockBackendEndpoint( - 200, objectMapper.writeValueAsString(new InventoryResponse(product.getCode(), 10))); + 200, + objectMapper.writeValueAsString( + new InventoryResponse(product.getProductCode(), 10))); webTestClient .get() @@ -269,8 +273,8 @@ void shouldRetryOnErrorAndFetchSuccessResponse() throws JsonProcessingException .expectBody() .jsonPath("$.id") .isEqualTo(product.getId()) - .jsonPath("$.code") - .isEqualTo(product.getCode()) + .jsonPath("$.productCode") + .isEqualTo(product.getProductCode()) .jsonPath("$.productName") .isEqualTo(product.getProductName()) .jsonPath("$.description") @@ -309,7 +313,9 @@ void shouldRetryOnErrorAndBreakCircuitResponse() throws JsonProcessingException Product product = savedProductList.getFirst(); Long productId = product.getId(); mockBackendEndpoint( - 200, objectMapper.writeValueAsString(new InventoryResponse(product.getCode(), 10))); + 200, + objectMapper.writeValueAsString( + new InventoryResponse(product.getProductCode(), 10))); webTestClient .get() @@ -344,7 +350,9 @@ void shouldRetryAndFailAndBreakCloseTheCircuitTest() throws JsonProcessingExcept mockBackendEndpoint(500, "ERROR"); mockBackendEndpoint(500, "ERROR"); mockBackendEndpoint( - 200, objectMapper.writeValueAsString(new InventoryResponse(product.getCode(), 10))); + 200, + objectMapper.writeValueAsString( + new InventoryResponse(product.getProductCode(), 10))); webTestClient .get() .uri("/api/catalog/id/{id}", productId) @@ -372,8 +380,8 @@ void shouldRetryAndFailAndBreakCloseTheCircuitTest() throws JsonProcessingExcept .expectBody() .jsonPath("$.id") .isEqualTo(product.getId()) - .jsonPath("$.code") - .isEqualTo(product.getCode()) + .jsonPath("$.productCode") + .isEqualTo(product.getProductCode()) .jsonPath("$.productName") .isEqualTo(product.getProductName()) .jsonPath("$.description") @@ -423,7 +431,7 @@ void shouldFindProductByProductCode() { webTestClient .get() - .uri("/api/catalog/productCode/{productCode}", product.getCode()) + .uri("/api/catalog/productCode/{productCode}", product.getProductCode()) .exchange() .expectStatus() .isOk() @@ -432,8 +440,8 @@ void shouldFindProductByProductCode() { .expectBody() .jsonPath("$.id") .isEqualTo(product.getId()) - .jsonPath("$.code") - .isEqualTo(product.getCode()) + .jsonPath("$.productCode") + .isEqualTo(product.getProductCode()) .jsonPath("$.productName") .isEqualTo(product.getProductName()) .jsonPath("$.description") @@ -449,7 +457,9 @@ void shouldFindProductByProductCodeWithStock() throws JsonProcessingException { Product product = savedProductList.getFirst(); mockBackendEndpoint( - 200, objectMapper.writeValueAsString(new InventoryResponse(product.getCode(), 10))); + 200, + objectMapper.writeValueAsString( + new InventoryResponse(product.getProductCode(), 10))); webTestClient .get() .uri( @@ -457,7 +467,7 @@ void shouldFindProductByProductCodeWithStock() throws JsonProcessingException { uriBuilder .path("/api/catalog/productCode/{productCode}") .queryParam("fetchInStock", true) - .build(product.getCode())) + .build(product.getProductCode())) .exchange() .expectStatus() .isOk() @@ -466,8 +476,8 @@ void shouldFindProductByProductCodeWithStock() throws JsonProcessingException { .expectBody() .jsonPath("$.id") .isEqualTo(product.getId()) - .jsonPath("$.code") - .isEqualTo(product.getCode()) + .jsonPath("$.productCode") + .isEqualTo(product.getProductCode()) .jsonPath("$.productName") .isEqualTo(product.getProductName()) .jsonPath("$.description") @@ -480,7 +490,8 @@ void shouldFindProductByProductCodeWithStock() throws JsonProcessingException { @Test void productsShouldExistsByProductCodes() { - List productCodeList = savedProductList.stream().map(Product::getCode).toList(); + List productCodeList = + savedProductList.stream().map(Product::getProductCode).toList(); webTestClient .get() @@ -539,8 +550,8 @@ void shouldCreateNewProduct() { .expectBody() .jsonPath("$.id") .isNotEmpty() - .jsonPath("$.code") - .isEqualTo(productRequest.code()) + .jsonPath("$.productCode") + .isEqualTo(productRequest.productCode()) .jsonPath("$.productName") .isEqualTo(productRequest.productName()) .jsonPath("$.description") @@ -622,7 +633,11 @@ void shouldUpdateProduct() { ProductRequest productRequest = new ProductRequest( - product.getCode(), product.getProductName(), "Updated Catalog", null, 100D); + product.getProductCode(), + product.getProductName(), + "Updated Catalog", + null, + 100D); webTestClient .put() @@ -637,8 +652,8 @@ void shouldUpdateProduct() { .expectBody() .jsonPath("$.id") .value(is(product.getId().intValue())) - .jsonPath("$.code") - .value(is(product.getCode())) + .jsonPath("$.productCode") + .value(is(product.getProductCode())) .jsonPath("$.productName") .value(is(product.getProductName())) .jsonPath("$.description") @@ -662,8 +677,8 @@ void shouldDeleteProduct() { .expectBody() .jsonPath("$.id") .isEqualTo(product.getId()) - .jsonPath("$.code") - .isEqualTo(product.getCode()) + .jsonPath("$.productCode") + .isEqualTo(product.getProductCode()) .jsonPath("$.productName") .isEqualTo(product.getProductName()) .jsonPath("$.description") diff --git a/catalog-service/src/test/java/com/example/catalogservice/web/controllers/ProductControllerTest.java b/catalog-service/src/test/java/com/example/catalogservice/web/controllers/ProductControllerTest.java index d1d26ede..e5c873e8 100644 --- a/catalog-service/src/test/java/com/example/catalogservice/web/controllers/ProductControllerTest.java +++ b/catalog-service/src/test/java/com/example/catalogservice/web/controllers/ProductControllerTest.java @@ -103,8 +103,8 @@ void shouldFindProductById() { .expectBody() .jsonPath("$.id") .isEqualTo(productResponse.id()) - .jsonPath("$.code") - .isEqualTo(productResponse.code()) + .jsonPath("$.productCode") + .isEqualTo(productResponse.productCode()) .jsonPath("$.productName") .isEqualTo(productResponse.productName()) .jsonPath("$.description") @@ -134,12 +134,13 @@ void shouldCreateProduct() { given(productService.saveProduct(any(ProductRequest.class))) .willReturn(Mono.just(productResponse)); - ProductDto productDto = new ProductDto("code 1", "name 1", "description 1", 9.0); + ProductRequest productRequest = + new ProductRequest("code 1", "name 1", "description 1", null, 9.0); webTestClient .post() .uri("/api/catalog") .contentType(MediaType.APPLICATION_JSON) - .body(Mono.just(productDto), ProductDto.class) + .body(Mono.just(productRequest), ProductRequest.class) .exchange() .expectStatus() .isCreated() @@ -150,14 +151,14 @@ void shouldCreateProduct() { .expectBody() .jsonPath("$.id") .isNotEmpty() - .jsonPath("$.code") - .isEqualTo(productDto.code()) + .jsonPath("$.productCode") + .isEqualTo(productResponse.productCode()) .jsonPath("$.productName") - .isEqualTo(productDto.productName()) + .isEqualTo(productResponse.productName()) .jsonPath("$.description") - .isEqualTo(productDto.description()) + .isEqualTo(productResponse.description()) .jsonPath("$.price") - .isEqualTo(productDto.price()); + .isEqualTo(productResponse.price()); } @Test @@ -193,7 +194,7 @@ void shouldUpdateProduct() { Product product = new Product() .setId(productId) - .setCode("code 1") + .setProductCode("code 1") .setProductName("Updated name") .setDescription("description 1") .setPrice(9.0); @@ -217,8 +218,8 @@ void shouldUpdateProduct() { .expectBody() .jsonPath("$.id") .value(is(1)) - .jsonPath("$.code") - .value(is(product.getCode())) + .jsonPath("$.productCode") + .value(is(product.getProductCode())) .jsonPath("$.productName") .value(is(product.getProductName())) .jsonPath("$.description") @@ -250,7 +251,7 @@ void shouldDeleteProduct() { Product product = new Product() .setId(productId) - .setCode("code 1") + .setProductCode("code 1") .setProductName("Updated name") .setDescription("description 1") .setPrice(9.0); @@ -268,8 +269,8 @@ void shouldDeleteProduct() { .expectBody() .jsonPath("$.id") .isEqualTo(product.getId()) - .jsonPath("$.code") - .isEqualTo(product.getCode()) + .jsonPath("$.productCode") + .isEqualTo(product.getProductCode()) .jsonPath("$.productName") .isEqualTo(product.getProductName()) .jsonPath("$.description") diff --git a/gatling-tests/src/test/java/simulation/CreateProductSimulation.java b/gatling-tests/src/test/java/simulation/CreateProductSimulation.java index aff1c194..d7639e2e 100644 --- a/gatling-tests/src/test/java/simulation/CreateProductSimulation.java +++ b/gatling-tests/src/test/java/simulation/CreateProductSimulation.java @@ -39,7 +39,8 @@ public class CreateProductSimulation extends Simulation { () -> { Map objectMap = new HashMap<>(); objectMap.put( - "code", "P000" + new SecureRandom().nextInt(10, 20_000)); + "productCode", + "P000" + new SecureRandom().nextInt(10, 20_000)); objectMap.put( "productName", "A Random Product" + new SecureRandom().nextInt()); @@ -58,7 +59,7 @@ public class CreateProductSimulation extends Simulation { .header("Content-Type", "application/json") .body( StringBody( - "{ \"code\": \"#{code}\",\"productName\":\"#{productName}\",\"price\":#{price}, \"description\": \"A Beautiful Product\" }")) + "{ \"productCode\": \"#{productCode}\",\"productName\":\"#{productName}\",\"price\":#{price}, \"description\": \"A Beautiful Product\" }")) .check(status().is(201)) .check(header("location").saveAs("location"))) .exec( @@ -70,7 +71,7 @@ public class CreateProductSimulation extends Simulation { .check(status().is(200))) .exec( http("get-inventory-request") - .get("/inventory-service/api/inventory/#{code}") + .get("/inventory-service/api/inventory/#{productCode}") .check(status().is(200)) .check(bodyString().saveAs("inventoryResponseBody"))) .exec( @@ -100,7 +101,7 @@ public class CreateProductSimulation extends Simulation { "customerId": #{customerId}, "items": [ { - "productCode": "#{code}", + "productCode": "#{productCode}", "quantity": 10, "productPrice": 5 } diff --git a/test-em-all.sh b/test-em-all.sh index 47cce9e5..35beda31 100755 --- a/test-em-all.sh +++ b/test-em-all.sh @@ -100,7 +100,7 @@ function recreateComposite() { function setupTestData() { - body="{\"code\":\"$PROD_CODE" + body="{\"productCode\":\"$PROD_CODE" body+=\ '","productName":"product name A","price":100, "imageUrl":"https://www.ikea.com/in/en/images/products/saellskaplig-jug-patterned-green__0941744_pe795674_s5.jpg?f=xl","description": "A Beautiful Product"}' @@ -108,7 +108,7 @@ function setupTestData() { echo "creating product with code - " $PROD_CODE recreateComposite "$PROD_CODE" "$body" "catalog-service/api/catalog" "POST" - body="{\"code\":\"$PROD_CODE_1" + body="{\"productCode\":\"$PROD_CODE_1" body+=\ '","productName":"product name B","price":9.99, "imageUrl":"https://cdn.igp.com/f_auto,q_auto,t_pnopt12prodlp/products/p-you-are-my-penguin-personalized-magic-mug-265224-m.jpg","description": "Nice Product"}'