From 3cde05a6ed82c398b617a687a2f99b8c6178fec5 Mon Sep 17 00:00:00 2001 From: Lukasz Rys Date: Sun, 17 Nov 2019 20:55:03 +0100 Subject: [PATCH] BAEL-2275: Add OrderItem --- .../ddd/layers/DomainLayerApplication.java | 4 +- .../layers/application/OrderController.java | 6 ++- .../request/CreateOrderRequest.java | 2 +- .../response/CreateOrderResponse.java | 2 +- .../ddd/layers/domain/DomainException.java | 7 ++++ .../com/baeldung/ddd/layers/domain/Order.java | 39 ++++++++++--------- .../baeldung/ddd/layers/domain/OrderItem.java | 33 ++++++++++++++++ .../baeldung/ddd/layers/domain/Product.java | 25 ++++++------ .../domain/exception/DomainException.java | 7 ---- .../domain/service/DomainOrderService.java | 14 ++++--- .../layers/domain/service/OrderService.java | 4 +- ...figuration.java => BeanConfiguration.java} | 2 +- .../ddd/layers/domain/OrderProvider.java | 3 +- .../ddd/layers/domain/OrderUnitTest.java | 32 +++++++++------ .../service/DomainOrderServiceUnitTest.java | 20 +++++----- 15 files changed, 127 insertions(+), 73 deletions(-) create mode 100644 ddd/src/main/java/com/baeldung/ddd/layers/domain/DomainException.java create mode 100644 ddd/src/main/java/com/baeldung/ddd/layers/domain/OrderItem.java delete mode 100644 ddd/src/main/java/com/baeldung/ddd/layers/domain/exception/DomainException.java rename ddd/src/main/java/com/baeldung/ddd/layers/infrastracture/configuration/{DomainConfiguration.java => BeanConfiguration.java} (95%) diff --git a/ddd/src/main/java/com/baeldung/ddd/layers/DomainLayerApplication.java b/ddd/src/main/java/com/baeldung/ddd/layers/DomainLayerApplication.java index 35fb1958e2..1a57311df8 100644 --- a/ddd/src/main/java/com/baeldung/ddd/layers/DomainLayerApplication.java +++ b/ddd/src/main/java/com/baeldung/ddd/layers/DomainLayerApplication.java @@ -5,9 +5,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.PropertySource; @SpringBootApplication -@PropertySource(value={"classpath:ddd-layers.properties"}) +@PropertySource(value = { "classpath:ddd-layers.properties" }) public class DomainLayerApplication { - public static void main(String[] args) { + public static void main(final String[] args) { SpringApplication.run(DomainLayerApplication.class, args); } } diff --git a/ddd/src/main/java/com/baeldung/ddd/layers/application/OrderController.java b/ddd/src/main/java/com/baeldung/ddd/layers/application/OrderController.java index 19aa0493fa..18f1514d05 100644 --- a/ddd/src/main/java/com/baeldung/ddd/layers/application/OrderController.java +++ b/ddd/src/main/java/com/baeldung/ddd/layers/application/OrderController.java @@ -9,6 +9,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; +import java.util.UUID; + @RestController @RequestMapping("/orders") public class OrderController { @@ -33,8 +35,8 @@ public class OrderController { } @DeleteMapping(value = "/{id}/products", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE) - void deleteProduct(@PathVariable final ObjectId id, @RequestParam final String name) { - orderService.deleteProduct(id, name); + void deleteProduct(@PathVariable final ObjectId id, @RequestParam final UUID productId) { + orderService.deleteProduct(id, productId); } @PostMapping("/{id}/complete") diff --git a/ddd/src/main/java/com/baeldung/ddd/layers/application/request/CreateOrderRequest.java b/ddd/src/main/java/com/baeldung/ddd/layers/application/request/CreateOrderRequest.java index 26d6d379c5..198feaf0d2 100644 --- a/ddd/src/main/java/com/baeldung/ddd/layers/application/request/CreateOrderRequest.java +++ b/ddd/src/main/java/com/baeldung/ddd/layers/application/request/CreateOrderRequest.java @@ -10,7 +10,7 @@ public class CreateOrderRequest { @NotNull private Product product; @JsonCreator - public CreateOrderRequest(@JsonProperty("product") @NotNull Product product) { + public CreateOrderRequest(@JsonProperty("product") @NotNull final Product product) { this.product = product; } diff --git a/ddd/src/main/java/com/baeldung/ddd/layers/application/response/CreateOrderResponse.java b/ddd/src/main/java/com/baeldung/ddd/layers/application/response/CreateOrderResponse.java index d57f297bde..04e5b89e6a 100644 --- a/ddd/src/main/java/com/baeldung/ddd/layers/application/response/CreateOrderResponse.java +++ b/ddd/src/main/java/com/baeldung/ddd/layers/application/response/CreateOrderResponse.java @@ -5,7 +5,7 @@ import org.bson.types.ObjectId; public class CreateOrderResponse { private final String id; - public CreateOrderResponse(String id) { + public CreateOrderResponse(final String id) { this.id = id; } diff --git a/ddd/src/main/java/com/baeldung/ddd/layers/domain/DomainException.java b/ddd/src/main/java/com/baeldung/ddd/layers/domain/DomainException.java new file mode 100644 index 0000000000..ca0dff4a69 --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/layers/domain/DomainException.java @@ -0,0 +1,7 @@ +package com.baeldung.ddd.layers.domain; + +class DomainException extends RuntimeException { + DomainException(final String message) { + super(message); + } +} diff --git a/ddd/src/main/java/com/baeldung/ddd/layers/domain/Order.java b/ddd/src/main/java/com/baeldung/ddd/layers/domain/Order.java index c41d856d33..99ad09b2e3 100644 --- a/ddd/src/main/java/com/baeldung/ddd/layers/domain/Order.java +++ b/ddd/src/main/java/com/baeldung/ddd/layers/domain/Order.java @@ -1,22 +1,22 @@ package com.baeldung.ddd.layers.domain; -import com.baeldung.ddd.layers.domain.exception.DomainException; import org.bson.types.ObjectId; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.UUID; public class Order { private final ObjectId id; private OrderStatus status; - private List products; + private List orderItems; private BigDecimal price; public Order(final ObjectId id, final Product product) { this.id = id; - this.products = new ArrayList<>(Collections.singletonList(product)); + this.orderItems = new ArrayList<>(Collections.singletonList(new OrderItem(product))); this.status = OrderStatus.CREATED; this.price = product.getPrice(); } @@ -26,29 +26,30 @@ public class Order { this.status = OrderStatus.COMPLETED; } - public void addProduct(final Product product) { + public void addOrder(final Product product) { validateState(); validateProduct(product); - products.add(product); + orderItems.add(new OrderItem(product)); price = price.add(product.getPrice()); } - public void removeProduct(final String name) { + public void removeOrder(final UUID id) { validateState(); - final Product product = getProduct(name); - products.remove(product); + final OrderItem orderItem = getOrderItem(id); + orderItems.remove(orderItem); - price = price.subtract(product.getPrice()); + price = price.subtract(orderItem.getPrice()); } - private Product getProduct(String name) { - return products + private OrderItem getOrderItem(final UUID id) { + return orderItems .stream() - .filter(product -> product - .getName() - .equals(name)) + .filter(orderItem -> orderItem + .getProduct() + .getId() + .equals(id)) .findFirst() - .orElseThrow(() -> new DomainException("Product with " + name + " doesn't exist.")); + .orElseThrow(() -> new DomainException("Product with " + id + " doesn't exist.")); } private void validateState() { @@ -71,11 +72,11 @@ public class Order { return status; } - public List getProducts() { - return Collections.unmodifiableList(products); - } - public BigDecimal getPrice() { return price; } + + public List getOrderItems() { + return orderItems; + } } diff --git a/ddd/src/main/java/com/baeldung/ddd/layers/domain/OrderItem.java b/ddd/src/main/java/com/baeldung/ddd/layers/domain/OrderItem.java new file mode 100644 index 0000000000..06b8bd69f4 --- /dev/null +++ b/ddd/src/main/java/com/baeldung/ddd/layers/domain/OrderItem.java @@ -0,0 +1,33 @@ +package com.baeldung.ddd.layers.domain; + +import java.math.BigDecimal; +import java.util.Objects; + +public class OrderItem { + private final Product product; + + public OrderItem(final Product product) { + this.product = product; + } + + public BigDecimal getPrice() { + return product.getPrice(); + } + + public Product getProduct() { + return product; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + OrderItem orderItem = (OrderItem) o; + return Objects.equals(product, orderItem.product); + } + + @Override + public int hashCode() { + return Objects.hash(product); + } +} diff --git a/ddd/src/main/java/com/baeldung/ddd/layers/domain/Product.java b/ddd/src/main/java/com/baeldung/ddd/layers/domain/Product.java index 286585d84a..31928fc0fd 100644 --- a/ddd/src/main/java/com/baeldung/ddd/layers/domain/Product.java +++ b/ddd/src/main/java/com/baeldung/ddd/layers/domain/Product.java @@ -5,13 +5,16 @@ import com.fasterxml.jackson.annotation.JsonProperty; import java.math.BigDecimal; import java.util.Objects; +import java.util.UUID; public class Product { + private final UUID id; private final BigDecimal price; private final String name; @JsonCreator - public Product(@JsonProperty("price") final BigDecimal price, @JsonProperty("name") final String name) { + public Product(@JsonProperty("id") final UUID id, @JsonProperty("price") final BigDecimal price, @JsonProperty("name") final String name) { + this.id = id; this.price = price; this.name = name; } @@ -24,20 +27,20 @@ public class Product { return name; } + public UUID getId() { + return id; + } + @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final Product product = (Product) o; - return Objects.equals(price, product.price) && Objects.equals(name, product.name); + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Product product = (Product) o; + return Objects.equals(id, product.id) && Objects.equals(price, product.price) && Objects.equals(name, product.name); } @Override public int hashCode() { - return Objects.hash(price, name); + return Objects.hash(id, price, name); } } diff --git a/ddd/src/main/java/com/baeldung/ddd/layers/domain/exception/DomainException.java b/ddd/src/main/java/com/baeldung/ddd/layers/domain/exception/DomainException.java deleted file mode 100644 index 05d25cc800..0000000000 --- a/ddd/src/main/java/com/baeldung/ddd/layers/domain/exception/DomainException.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.baeldung.ddd.layers.domain.exception; - -public class DomainException extends RuntimeException { - public DomainException(final String message) { - super(message); - } -} diff --git a/ddd/src/main/java/com/baeldung/ddd/layers/domain/service/DomainOrderService.java b/ddd/src/main/java/com/baeldung/ddd/layers/domain/service/DomainOrderService.java index 6ccef2e842..ceaf7de863 100644 --- a/ddd/src/main/java/com/baeldung/ddd/layers/domain/service/DomainOrderService.java +++ b/ddd/src/main/java/com/baeldung/ddd/layers/domain/service/DomainOrderService.java @@ -5,11 +5,13 @@ import com.baeldung.ddd.layers.domain.Product; import com.baeldung.ddd.layers.domain.repository.OrderRepository; import org.bson.types.ObjectId; +import java.util.UUID; + public class DomainOrderService implements OrderService { private final OrderRepository orderRepository; - public DomainOrderService(OrderRepository orderRepository) { + public DomainOrderService(final OrderRepository orderRepository) { this.orderRepository = orderRepository; } @@ -22,15 +24,15 @@ public class DomainOrderService implements OrderService { } @Override - public void addProduct(ObjectId id, Product product) { + public void addProduct(final ObjectId id, final Product product) { final Order order = getOrder(id); - order.addProduct(product); + order.addOrder(product); orderRepository.save(order); } @Override - public void completeOrder(ObjectId id) { + public void completeOrder(final ObjectId id) { final Order order = getOrder(id); order.complete(); @@ -38,9 +40,9 @@ public class DomainOrderService implements OrderService { } @Override - public void deleteProduct(ObjectId id, String name) { + public void deleteProduct(final ObjectId id, final UUID productId) { final Order order = getOrder(id); - order.removeProduct(name); + order.removeOrder(productId); orderRepository.save(order); } diff --git a/ddd/src/main/java/com/baeldung/ddd/layers/domain/service/OrderService.java b/ddd/src/main/java/com/baeldung/ddd/layers/domain/service/OrderService.java index b00d5b286a..ed3ffe5ed3 100644 --- a/ddd/src/main/java/com/baeldung/ddd/layers/domain/service/OrderService.java +++ b/ddd/src/main/java/com/baeldung/ddd/layers/domain/service/OrderService.java @@ -3,6 +3,8 @@ package com.baeldung.ddd.layers.domain.service; import com.baeldung.ddd.layers.domain.Product; import org.bson.types.ObjectId; +import java.util.UUID; + public interface OrderService { ObjectId createOrder(final Product product); @@ -10,5 +12,5 @@ public interface OrderService { void completeOrder(ObjectId id); - void deleteProduct(ObjectId id, String name); + void deleteProduct(ObjectId id, UUID productId); } diff --git a/ddd/src/main/java/com/baeldung/ddd/layers/infrastracture/configuration/DomainConfiguration.java b/ddd/src/main/java/com/baeldung/ddd/layers/infrastracture/configuration/BeanConfiguration.java similarity index 95% rename from ddd/src/main/java/com/baeldung/ddd/layers/infrastracture/configuration/DomainConfiguration.java rename to ddd/src/main/java/com/baeldung/ddd/layers/infrastracture/configuration/BeanConfiguration.java index 8e97b4ca01..68429f1fb8 100644 --- a/ddd/src/main/java/com/baeldung/ddd/layers/infrastracture/configuration/DomainConfiguration.java +++ b/ddd/src/main/java/com/baeldung/ddd/layers/infrastracture/configuration/BeanConfiguration.java @@ -10,7 +10,7 @@ import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan(basePackageClasses = DomainLayerApplication.class) -public class DomainConfiguration { +public class BeanConfiguration { @Bean OrderService orderService(final OrderRepository orderRepository) { diff --git a/ddd/src/test/java/com/baeldung/ddd/layers/domain/OrderProvider.java b/ddd/src/test/java/com/baeldung/ddd/layers/domain/OrderProvider.java index 8b86992ad5..5133ece1b8 100644 --- a/ddd/src/test/java/com/baeldung/ddd/layers/domain/OrderProvider.java +++ b/ddd/src/test/java/com/baeldung/ddd/layers/domain/OrderProvider.java @@ -3,10 +3,11 @@ package com.baeldung.ddd.layers.domain; import org.bson.types.ObjectId; import java.math.BigDecimal; +import java.util.UUID; public class OrderProvider { public static Order getCreatedOrder() { - return new Order(ObjectId.get(), new Product(BigDecimal.TEN, "productName")); + return new Order(ObjectId.get(), new Product(UUID.randomUUID(), BigDecimal.TEN, "productName")); } public static Order getCompletedOrder() { diff --git a/ddd/src/test/java/com/baeldung/ddd/layers/domain/OrderUnitTest.java b/ddd/src/test/java/com/baeldung/ddd/layers/domain/OrderUnitTest.java index 0996383610..48c55769ab 100644 --- a/ddd/src/test/java/com/baeldung/ddd/layers/domain/OrderUnitTest.java +++ b/ddd/src/test/java/com/baeldung/ddd/layers/domain/OrderUnitTest.java @@ -1,13 +1,11 @@ package com.baeldung.ddd.layers.domain; -import com.baeldung.ddd.layers.domain.exception.DomainException; -import org.bson.types.ObjectId; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; import java.math.BigDecimal; -import java.util.Arrays; +import java.util.UUID; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -25,22 +23,26 @@ class OrderUnitTest { @Test void shouldAddProduct_thenUpdatePrice() { final Order order = OrderProvider.getCreatedOrder(); - final int orderOriginalProductSize = order.getProducts().size(); + final int orderOriginalProductSize = order + .getOrderItems() + .size(); final BigDecimal orderOriginalPrice = order.getPrice(); - final Product productToAdd = new Product(new BigDecimal("20"), "secondProduct"); + final Product productToAdd = new Product(UUID.randomUUID(), new BigDecimal("20"), "secondProduct"); - order.addProduct(productToAdd); + order.addOrder(productToAdd); - assertEquals(orderOriginalProductSize + 1, order.getProducts().size()); + assertEquals(orderOriginalProductSize + 1, order + .getOrderItems() + .size()); assertEquals(orderOriginalPrice.add(productToAdd.getPrice()), order.getPrice()); } @Test - void shouldAddProduct_thenThrowException(){ + void shouldAddProduct_thenThrowException() { final Order order = OrderProvider.getCompletedOrder(); - final Product productToAdd = new Product(new BigDecimal("20"), "secondProduct"); + final Product productToAdd = new Product(UUID.randomUUID(), new BigDecimal("20"), "secondProduct"); - final Executable executable = () -> order.addProduct(productToAdd); + final Executable executable = () -> order.addOrder(productToAdd); Assertions.assertThrows(DomainException.class, executable); } @@ -49,9 +51,15 @@ class OrderUnitTest { void shouldRemoveProduct_thenUpdatePrice() { final Order order = OrderProvider.getCreatedOrder(); - order.removeProduct(order.getProducts().get(0).getName()); + order.removeOrder(order + .getOrderItems() + .get(0) + .getProduct() + .getId()); - assertEquals(0, order.getProducts().size()); + assertEquals(0, order + .getOrderItems() + .size()); assertEquals(BigDecimal.ZERO, order.getPrice()); } } \ No newline at end of file diff --git a/ddd/src/test/java/com/baeldung/ddd/layers/domain/service/DomainOrderServiceUnitTest.java b/ddd/src/test/java/com/baeldung/ddd/layers/domain/service/DomainOrderServiceUnitTest.java index 3ac40a867e..572afada00 100644 --- a/ddd/src/test/java/com/baeldung/ddd/layers/domain/service/DomainOrderServiceUnitTest.java +++ b/ddd/src/test/java/com/baeldung/ddd/layers/domain/service/DomainOrderServiceUnitTest.java @@ -11,6 +11,7 @@ import org.junit.jupiter.api.function.Executable; import java.math.BigDecimal; import java.util.Optional; +import java.util.UUID; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -30,7 +31,7 @@ class DomainOrderServiceUnitTest { @Test void shouldCreateOrder_thenSaveIt() { - final Product product = new Product(BigDecimal.TEN, "productName"); + final Product product = new Product(UUID.randomUUID(), BigDecimal.TEN, "productName"); final ObjectId id = tested.createOrder(product); @@ -41,18 +42,18 @@ class DomainOrderServiceUnitTest { @Test void shouldAddProduct_thenSaveOrder() { final Order order = spy(OrderProvider.getCreatedOrder()); - final Product product = new Product(BigDecimal.TEN, "test"); + final Product product = new Product(UUID.randomUUID(), BigDecimal.TEN, "test"); when(orderRepository.findById(order.getId())).thenReturn(Optional.of(order)); tested.addProduct(order.getId(), product); verify(orderRepository).save(order); - verify(order).addProduct(product); + verify(order).addOrder(product); } @Test void shouldAddProduct_thenThrowException() { - final Product product = new Product(BigDecimal.TEN, "test"); + final Product product = new Product(UUID.randomUUID(), BigDecimal.TEN, "test"); final ObjectId id = ObjectId.get(); when(orderRepository.findById(id)).thenReturn(Optional.empty()); @@ -76,15 +77,16 @@ class DomainOrderServiceUnitTest { @Test void shouldDeleteProduct_thenSaveOrder() { final Order order = spy(OrderProvider.getCreatedOrder()); - final String productName = order - .getProducts() + final UUID productId = order + .getOrderItems() .get(0) - .getName(); + .getProduct() + .getId(); when(orderRepository.findById(order.getId())).thenReturn(Optional.of(order)); - tested.deleteProduct(order.getId(), productName); + tested.deleteProduct(order.getId(), productId); verify(orderRepository).save(order); - verify(order).removeProduct(productName); + verify(order).removeOrder(productId); } } \ No newline at end of file