diff --git a/ddd-modules/README.md b/ddd-modules/README.md
new file mode 100644
index 0000000000..5616cce48b
--- /dev/null
+++ b/ddd-modules/README.md
@@ -0,0 +1 @@
+## Relevant Articles
diff --git a/ddd-modules/infrastructure/pom.xml b/ddd-modules/infrastructure/pom.xml
new file mode 100644
index 0000000000..72ec263745
--- /dev/null
+++ b/ddd-modules/infrastructure/pom.xml
@@ -0,0 +1,53 @@
+
+
+ 4.0.0
+ com.baeldung.dddmodules.infrastructure
+ infrastructure
+ 1.0
+
+ jar
+
+
+ com.baeldung.dddmodules
+ dddmodules
+ 1.0
+
+
+
+
+ com.baeldung.dddmodules.shippingcontext
+ shippingcontext
+ ${appmodules.version}
+
+
+ com.baeldung.dddmodules.ordercontext
+ ordercontext
+ ${appmodules.version}
+
+
+ com.baeldung.dddmodules.sharedkernel
+ sharedkernel
+ ${appmodules.version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ ${source.version}
+ ${target.version}
+
+
+
+
+
+
+ 9
+ 9
+
+
+
\ No newline at end of file
diff --git a/ddd-modules/infrastructure/src/main/java/com/baeldung/dddmodules/infrastructure/db/InMemoryOrderStore.java b/ddd-modules/infrastructure/src/main/java/com/baeldung/dddmodules/infrastructure/db/InMemoryOrderStore.java
new file mode 100644
index 0000000000..13deb2471e
--- /dev/null
+++ b/ddd-modules/infrastructure/src/main/java/com/baeldung/dddmodules/infrastructure/db/InMemoryOrderStore.java
@@ -0,0 +1,79 @@
+package com.baeldung.dddmodules.infrastructure.db;
+
+import com.baeldung.dddmodules.ordercontext.model.CustomerOrder;
+import com.baeldung.dddmodules.ordercontext.repository.CustomerOrderRepository;
+import com.baeldung.dddmodules.shippingcontext.model.PackageItem;
+import com.baeldung.dddmodules.shippingcontext.model.ShippableOrder;
+import com.baeldung.dddmodules.shippingcontext.repository.ShippingOrderRepository;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+public class InMemoryOrderStore implements CustomerOrderRepository, ShippingOrderRepository {
+ private Map ordersDb = new HashMap<>();
+ private volatile static InMemoryOrderStore instance = new InMemoryOrderStore();
+
+ @Override
+ public void saveCustomerOrder(CustomerOrder order) {
+ this.ordersDb.put(order.getOrderId(), new PersistenceOrder(order.getOrderId(),
+ order.getPaymentMethod(),
+ order.getAddress(),
+ order
+ .getOrderItems()
+ .stream()
+ .map(orderItem ->
+ new PersistenceOrder.OrderItem(orderItem.getProductId(),
+ orderItem.getQuantity(),
+ orderItem.getUnitWeight(),
+ orderItem.getUnitPrice()))
+ .collect(Collectors.toList())
+ ));
+ }
+
+ @Override
+ public Optional findShippableOrder(int orderId) {
+ if (!this.ordersDb.containsKey(orderId)) return Optional.empty();
+ PersistenceOrder orderRecord = this.ordersDb.get(orderId);
+ return Optional.of(
+ new ShippableOrder(orderRecord.orderId, orderRecord.orderItems
+ .stream().map(orderItem -> new PackageItem(orderItem.productId,
+ orderItem.itemWeight,
+ orderItem.quantity * orderItem.unitPrice)
+ ).collect(Collectors.toList())));
+ }
+
+ public static InMemoryOrderStore provider() {
+ return instance;
+ }
+
+ public static class PersistenceOrder {
+ public int orderId;
+ public String paymentMethod;
+ public String address;
+ public List orderItems;
+
+ public PersistenceOrder(int orderId, String paymentMethod, String address, List orderItems) {
+ this.orderId = orderId;
+ this.paymentMethod = paymentMethod;
+ this.address = address;
+ this.orderItems = orderItems;
+ }
+
+ public static class OrderItem {
+ public int productId;
+ public float unitPrice;
+ public float itemWeight;
+ public int quantity;
+
+ public OrderItem(int productId, int quantity, float unitWeight, float unitPrice) {
+ this.itemWeight = unitWeight;
+ this.quantity = quantity;
+ this.unitPrice = unitPrice;
+ this.productId = productId;
+ }
+ }
+ }
+}
diff --git a/ddd-modules/infrastructure/src/main/java/com/baeldung/dddmodules/infrastructure/events/SimpleEventBus.java b/ddd-modules/infrastructure/src/main/java/com/baeldung/dddmodules/infrastructure/events/SimpleEventBus.java
new file mode 100644
index 0000000000..6aea7ff6e9
--- /dev/null
+++ b/ddd-modules/infrastructure/src/main/java/com/baeldung/dddmodules/infrastructure/events/SimpleEventBus.java
@@ -0,0 +1,39 @@
+package com.baeldung.dddmodules.infrastructure.events;
+
+import com.baeldung.dddmodules.sharedkernel.events.ApplicationEvent;
+import com.baeldung.dddmodules.sharedkernel.events.EventBus;
+import com.baeldung.dddmodules.sharedkernel.events.EventSubscriber;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+public class SimpleEventBus implements EventBus {
+ private final Map> subscribers = new ConcurrentHashMap<>();
+
+ @Override
+ public void publish(E event) {
+ if (subscribers.containsKey(event.getType())) {
+ subscribers.get(event.getType())
+ .forEach(subscriber -> subscriber.onEvent(event));
+ }
+ }
+
+ @Override
+ public void subscribe(String eventType, EventSubscriber subscriber) {
+ Set eventSubscribers = subscribers.get(eventType);
+ if (eventSubscribers == null) {
+ eventSubscribers = new CopyOnWriteArraySet<>();
+ subscribers.put(eventType, eventSubscribers);
+ }
+ eventSubscribers.add(subscriber);
+ }
+
+ @Override
+ public void unsubscribe(String eventType, EventSubscriber subscriber) {
+ if (subscribers.containsKey(eventType)) {
+ subscribers.get(eventType).remove(subscriber);
+ }
+ }
+}
diff --git a/ddd-modules/infrastructure/src/main/java/module-info.java b/ddd-modules/infrastructure/src/main/java/module-info.java
new file mode 100644
index 0000000000..19f7b36548
--- /dev/null
+++ b/ddd-modules/infrastructure/src/main/java/module-info.java
@@ -0,0 +1,11 @@
+module com.baeldung.dddmodules.infrastructure {
+ requires transitive com.baeldung.dddmodules.sharedkernel;
+ requires transitive com.baeldung.dddmodules.ordercontext;
+ requires transitive com.baeldung.dddmodules.shippingcontext;
+ provides com.baeldung.dddmodules.sharedkernel.events.EventBus
+ with com.baeldung.dddmodules.infrastructure.events.SimpleEventBus;
+ provides com.baeldung.dddmodules.ordercontext.repository.CustomerOrderRepository
+ with com.baeldung.dddmodules.infrastructure.db.InMemoryOrderStore;
+ provides com.baeldung.dddmodules.shippingcontext.repository.ShippingOrderRepository
+ with com.baeldung.dddmodules.infrastructure.db.InMemoryOrderStore;
+}
diff --git a/ddd-modules/mainapp/pom.xml b/ddd-modules/mainapp/pom.xml
new file mode 100644
index 0000000000..ae1057f307
--- /dev/null
+++ b/ddd-modules/mainapp/pom.xml
@@ -0,0 +1,51 @@
+
+
+ 4.0.0
+ com.baeldung.dddmodules.mainapp
+ mainapp
+ 1.0
+ jar
+
+
+ com.baeldung.dddmodules
+ dddmodules
+ 1.0
+
+
+
+
+ com.baeldung.dddmodules.infrastructure
+ infrastructure
+ ${appmodules.version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.16
+
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${compiler.plugin.version}
+
+ ${source.version}
+ ${target.version}
+
+
+
+
+
+
+ 9
+ 9
+
+
+
\ No newline at end of file
diff --git a/ddd-modules/mainapp/src/main/java/com/baeldung/dddmodules/mainapp/Application.java b/ddd-modules/mainapp/src/main/java/com/baeldung/dddmodules/mainapp/Application.java
new file mode 100644
index 0000000000..05e27abe30
--- /dev/null
+++ b/ddd-modules/mainapp/src/main/java/com/baeldung/dddmodules/mainapp/Application.java
@@ -0,0 +1,54 @@
+package com.baeldung.dddmodules.mainapp;
+
+import com.baeldung.dddmodules.ordercontext.model.CustomerOrder;
+import com.baeldung.dddmodules.ordercontext.model.OrderItem;
+import com.baeldung.dddmodules.ordercontext.repository.CustomerOrderRepository;
+import com.baeldung.dddmodules.ordercontext.service.OrderService;
+import com.baeldung.dddmodules.sharedkernel.events.EventBus;
+import com.baeldung.dddmodules.shippingcontext.repository.ShippingOrderRepository;
+import com.baeldung.dddmodules.shippingcontext.service.ShippingService;
+
+import java.util.*;
+
+public class Application {
+
+ public static void main(String args[]) {
+ Map, Object> container = createContainer();
+ OrderService orderService = (OrderService) container.get(OrderService.class);
+ ShippingService shippingService = (ShippingService) container.get(ShippingService.class);
+ shippingService.listenToOrderEvents();
+
+ CustomerOrder customerOrder = new CustomerOrder();
+ int orderId = 1;
+ customerOrder.setOrderId(orderId);
+ List orderItems = new ArrayList();
+ orderItems.add(new OrderItem(1, 2, 3, 1));
+ orderItems.add(new OrderItem(2, 1, 1, 1));
+ orderItems.add(new OrderItem(3, 4, 11, 21));
+ customerOrder.setOrderItems(orderItems);
+ customerOrder.setPaymentMethod("PayPal");
+ customerOrder.setAddress("Full address here");
+ orderService.placeOrder(customerOrder);
+
+ if (orderId == shippingService.getParcelByOrderId(orderId).get().getOrderId()) {
+ System.out.println("Order has been processed and shipped successfully");
+ }
+ }
+
+ public static Map, Object> createContainer() {
+ EventBus eventBus = ServiceLoader.load(EventBus.class).findFirst().get();
+ CustomerOrderRepository customerOrderRepository = ServiceLoader.load(CustomerOrderRepository.class).findFirst().get();
+ ShippingOrderRepository shippingOrderRepository = ServiceLoader.load(ShippingOrderRepository.class).findFirst().get();
+ ShippingService shippingService = ServiceLoader.load(ShippingService.class).findFirst().get();
+ shippingService.setEventBus(eventBus);
+ shippingService.setOrderRepository(shippingOrderRepository);
+ OrderService orderService = ServiceLoader.load(OrderService.class).findFirst().get();
+ orderService.setEventBus(eventBus);
+ orderService.setOrderRepository(customerOrderRepository);
+ HashMap, Object> container = new HashMap<>();
+ container.put(OrderService.class, orderService);
+ container.put(ShippingService.class, shippingService);
+ return container;
+ }
+
+}
diff --git a/ddd-modules/mainapp/src/main/java/module-info.java b/ddd-modules/mainapp/src/main/java/module-info.java
new file mode 100644
index 0000000000..356b03731c
--- /dev/null
+++ b/ddd-modules/mainapp/src/main/java/module-info.java
@@ -0,0 +1,8 @@
+module com.baeldung.dddmodules.mainapp {
+ uses com.baeldung.dddmodules.sharedkernel.events.EventBus;
+ uses com.baeldung.dddmodules.ordercontext.service.OrderService;
+ uses com.baeldung.dddmodules.ordercontext.repository.CustomerOrderRepository;
+ uses com.baeldung.dddmodules.shippingcontext.repository.ShippingOrderRepository;
+ uses com.baeldung.dddmodules.shippingcontext.service.ShippingService;
+ requires transitive com.baeldung.dddmodules.infrastructure;
+}
\ No newline at end of file
diff --git a/ddd-modules/ordercontext/pom.xml b/ddd-modules/ordercontext/pom.xml
new file mode 100644
index 0000000000..6a921d2408
--- /dev/null
+++ b/ddd-modules/ordercontext/pom.xml
@@ -0,0 +1,44 @@
+
+
+ 4.0.0
+ com.baeldung.dddmodules.ordercontext
+ ordercontext
+ 1.0
+ jar
+
+
+ com.baeldung.dddmodules
+ dddmodules
+ 1.0
+
+
+
+
+ com.baeldung.dddmodules.sharedkernel
+ sharedkernel
+ ${appmodules.version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ ${source.version}
+ ${target.version}
+
+
+
+
+
+
+ 9
+ 9
+ 1.0
+ 1.0
+
+
+
\ No newline at end of file
diff --git a/ddd-modules/ordercontext/src/main/java/com/baeldung/dddmodules/ordercontext/model/CustomerOrder.java b/ddd-modules/ordercontext/src/main/java/com/baeldung/dddmodules/ordercontext/model/CustomerOrder.java
new file mode 100644
index 0000000000..ee87de56bd
--- /dev/null
+++ b/ddd-modules/ordercontext/src/main/java/com/baeldung/dddmodules/ordercontext/model/CustomerOrder.java
@@ -0,0 +1,51 @@
+package com.baeldung.dddmodules.ordercontext.model;
+
+import java.util.List;
+
+public class CustomerOrder {
+ private int orderId;
+ private String paymentMethod;
+ private String address;
+ private List orderItems;
+
+ public CustomerOrder() {
+
+ }
+
+ public float calculateTotalPrice() {
+ return orderItems.stream().map(OrderItem::getTotalPrice)
+ .reduce(0F, Float::sum);
+ }
+
+ public void setOrderItems(List orderItems) {
+ this.orderItems = orderItems;
+ }
+
+ public int getOrderId() {
+ return orderId;
+ }
+
+ public List getOrderItems() {
+ return orderItems;
+ }
+
+ public void setOrderId(int orderId) {
+ this.orderId = orderId;
+ }
+
+ public String getPaymentMethod() {
+ return paymentMethod;
+ }
+
+ public void setPaymentMethod(String paymentMethod) {
+ this.paymentMethod = paymentMethod;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+}
diff --git a/ddd-modules/ordercontext/src/main/java/com/baeldung/dddmodules/ordercontext/model/OrderItem.java b/ddd-modules/ordercontext/src/main/java/com/baeldung/dddmodules/ordercontext/model/OrderItem.java
new file mode 100644
index 0000000000..aaad0777e4
--- /dev/null
+++ b/ddd-modules/ordercontext/src/main/java/com/baeldung/dddmodules/ordercontext/model/OrderItem.java
@@ -0,0 +1,51 @@
+package com.baeldung.dddmodules.ordercontext.model;
+
+public class OrderItem {
+ private int productId;
+ private int quantity;
+ private float unitPrice;
+ private float unitWeight;
+
+ public OrderItem(int productId, int quantity, float unitPrice, float unitWeight) {
+ this.productId = productId;
+ this.quantity = quantity;
+ this.unitPrice = unitPrice;
+ this.unitWeight = unitWeight;
+ }
+
+ public int getProductId() {
+ return productId;
+ }
+
+ public void setProductId(int productId) {
+ this.productId = productId;
+ }
+
+ public int getQuantity() {
+ return quantity;
+ }
+
+ public void setQuantity(int quantity) {
+ this.quantity = quantity;
+ }
+
+ public float getTotalPrice() {
+ return this.quantity * this.unitPrice;
+ }
+
+ public void setUnitPrice(float unitPrice) {
+ this.unitPrice = unitPrice;
+ }
+
+ public float getUnitWeight() {
+ return unitWeight;
+ }
+
+ public float getUnitPrice() {
+ return unitPrice;
+ }
+
+ public void setUnitWeight(float unitWeight) {
+ this.unitWeight = unitWeight;
+ }
+}
diff --git a/ddd-modules/ordercontext/src/main/java/com/baeldung/dddmodules/ordercontext/repository/CustomerOrderRepository.java b/ddd-modules/ordercontext/src/main/java/com/baeldung/dddmodules/ordercontext/repository/CustomerOrderRepository.java
new file mode 100644
index 0000000000..771bbf3301
--- /dev/null
+++ b/ddd-modules/ordercontext/src/main/java/com/baeldung/dddmodules/ordercontext/repository/CustomerOrderRepository.java
@@ -0,0 +1,7 @@
+package com.baeldung.dddmodules.ordercontext.repository;
+
+import com.baeldung.dddmodules.ordercontext.model.CustomerOrder;
+
+public interface CustomerOrderRepository {
+ void saveCustomerOrder(CustomerOrder order);
+}
diff --git a/ddd-modules/ordercontext/src/main/java/com/baeldung/dddmodules/ordercontext/service/CustomerOrderService.java b/ddd-modules/ordercontext/src/main/java/com/baeldung/dddmodules/ordercontext/service/CustomerOrderService.java
new file mode 100644
index 0000000000..b9d26e6212
--- /dev/null
+++ b/ddd-modules/ordercontext/src/main/java/com/baeldung/dddmodules/ordercontext/service/CustomerOrderService.java
@@ -0,0 +1,44 @@
+package com.baeldung.dddmodules.ordercontext.service;
+
+import com.baeldung.dddmodules.ordercontext.model.CustomerOrder;
+import com.baeldung.dddmodules.ordercontext.repository.CustomerOrderRepository;
+import com.baeldung.dddmodules.sharedkernel.events.ApplicationEvent;
+import com.baeldung.dddmodules.sharedkernel.events.EventBus;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class CustomerOrderService implements OrderService {
+ public static final String EVENT_ORDER_READY_FOR_SHIPMENT = "OrderReadyForShipmentEvent";
+
+ private CustomerOrderRepository orderRepository;
+ private EventBus eventBus;
+
+ @Override
+ public void placeOrder(CustomerOrder order) {
+ this.orderRepository.saveCustomerOrder(order);
+ Map payload = new HashMap<>();
+ payload.put("order_id", String.valueOf(order.getOrderId()));
+ ApplicationEvent event = new ApplicationEvent(payload) {
+ @Override
+ public String getType() {
+ return EVENT_ORDER_READY_FOR_SHIPMENT;
+ }
+ };
+ this.eventBus.publish(event);
+ }
+
+ @Override
+ public EventBus getEventBus() {
+ return eventBus;
+ }
+
+ public void setOrderRepository(CustomerOrderRepository orderRepository) {
+ this.orderRepository = orderRepository;
+ }
+
+ @Override
+ public void setEventBus(EventBus eventBus) {
+ this.eventBus = eventBus;
+ }
+}
diff --git a/ddd-modules/ordercontext/src/main/java/com/baeldung/dddmodules/ordercontext/service/OrderService.java b/ddd-modules/ordercontext/src/main/java/com/baeldung/dddmodules/ordercontext/service/OrderService.java
new file mode 100644
index 0000000000..1bbb8b8398
--- /dev/null
+++ b/ddd-modules/ordercontext/src/main/java/com/baeldung/dddmodules/ordercontext/service/OrderService.java
@@ -0,0 +1,11 @@
+package com.baeldung.dddmodules.ordercontext.service;
+
+import com.baeldung.dddmodules.ordercontext.model.CustomerOrder;
+import com.baeldung.dddmodules.ordercontext.repository.CustomerOrderRepository;
+import com.baeldung.dddmodules.sharedkernel.service.ApplicationService;
+
+public interface OrderService extends ApplicationService {
+ void placeOrder(CustomerOrder order);
+
+ void setOrderRepository(CustomerOrderRepository orderRepository);
+}
diff --git a/ddd-modules/ordercontext/src/main/java/module-info.java b/ddd-modules/ordercontext/src/main/java/module-info.java
new file mode 100644
index 0000000000..e9b7cf9535
--- /dev/null
+++ b/ddd-modules/ordercontext/src/main/java/module-info.java
@@ -0,0 +1,8 @@
+module com.baeldung.dddmodules.ordercontext {
+ requires com.baeldung.dddmodules.sharedkernel;
+ exports com.baeldung.dddmodules.ordercontext.service;
+ exports com.baeldung.dddmodules.ordercontext.model;
+ exports com.baeldung.dddmodules.ordercontext.repository;
+ provides com.baeldung.dddmodules.ordercontext.service.OrderService
+ with com.baeldung.dddmodules.ordercontext.service.CustomerOrderService;
+}
\ No newline at end of file
diff --git a/ddd-modules/pom.xml b/ddd-modules/pom.xml
new file mode 100644
index 0000000000..65bc204988
--- /dev/null
+++ b/ddd-modules/pom.xml
@@ -0,0 +1,68 @@
+
+
+ 4.0.0
+ com.baeldung.dddmodules
+ dddmodules
+ 1.0
+ ddd-modules
+ pom
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+ ../
+
+
+
+ sharedkernel
+ infrastructure
+ shippingcontext
+ ordercontext
+ mainapp
+
+
+
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+ org.assertj
+ assertj-core
+ ${assertj-core.version}
+ test
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${compiler.plugin.version}
+
+ ${source.version}
+ ${target.version}
+
+
+
+
+
+
+
+ 3.8.1
+ 9
+ 9
+ UTF-8
+ 3.12.2
+ 1.0
+
+
+
diff --git a/ddd-modules/sharedkernel/pom.xml b/ddd-modules/sharedkernel/pom.xml
new file mode 100644
index 0000000000..3b5d8bb71f
--- /dev/null
+++ b/ddd-modules/sharedkernel/pom.xml
@@ -0,0 +1,34 @@
+
+
+ 4.0.0
+ com.baeldung.dddmodules.sharedkernel
+ sharedkernel
+ 1.0
+ jar
+
+
+ com.baeldung.dddmodules
+ dddmodules
+ 1.0
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ ${source.version}
+ ${target.version}
+
+
+
+
+
+
+ 9
+ 9
+
+
+
\ No newline at end of file
diff --git a/ddd-modules/sharedkernel/src/main/java/com/baeldung/dddmodules/sharedkernel/events/ApplicationEvent.java b/ddd-modules/sharedkernel/src/main/java/com/baeldung/dddmodules/sharedkernel/events/ApplicationEvent.java
new file mode 100644
index 0000000000..e3c3ebaf0e
--- /dev/null
+++ b/ddd-modules/sharedkernel/src/main/java/com/baeldung/dddmodules/sharedkernel/events/ApplicationEvent.java
@@ -0,0 +1,21 @@
+package com.baeldung.dddmodules.sharedkernel.events;
+
+import java.util.Map;
+
+public abstract class ApplicationEvent {
+ protected Map payload;
+
+ public abstract String getType();
+
+ public String getPayloadValue(String key) {
+ if (this.payload.containsKey(key)) {
+ return this.payload.get(key);
+ }
+ return "";
+ }
+
+ public ApplicationEvent(Map payload) {
+ this.payload = payload;
+ }
+}
+
diff --git a/ddd-modules/sharedkernel/src/main/java/com/baeldung/dddmodules/sharedkernel/events/EventBus.java b/ddd-modules/sharedkernel/src/main/java/com/baeldung/dddmodules/sharedkernel/events/EventBus.java
new file mode 100644
index 0000000000..b128b959e9
--- /dev/null
+++ b/ddd-modules/sharedkernel/src/main/java/com/baeldung/dddmodules/sharedkernel/events/EventBus.java
@@ -0,0 +1,9 @@
+package com.baeldung.dddmodules.sharedkernel.events;
+
+public interface EventBus {
+ void publish(E event);
+
+ void subscribe(String eventType, EventSubscriber subscriber);
+
+ void unsubscribe(String eventType, EventSubscriber subscriber);
+}
diff --git a/ddd-modules/sharedkernel/src/main/java/com/baeldung/dddmodules/sharedkernel/events/EventSubscriber.java b/ddd-modules/sharedkernel/src/main/java/com/baeldung/dddmodules/sharedkernel/events/EventSubscriber.java
new file mode 100644
index 0000000000..0d6d48cc33
--- /dev/null
+++ b/ddd-modules/sharedkernel/src/main/java/com/baeldung/dddmodules/sharedkernel/events/EventSubscriber.java
@@ -0,0 +1,5 @@
+package com.baeldung.dddmodules.sharedkernel.events;
+
+public interface EventSubscriber {
+ void onEvent(E event);
+}
diff --git a/ddd-modules/sharedkernel/src/main/java/com/baeldung/dddmodules/sharedkernel/service/ApplicationService.java b/ddd-modules/sharedkernel/src/main/java/com/baeldung/dddmodules/sharedkernel/service/ApplicationService.java
new file mode 100644
index 0000000000..5ef57ae269
--- /dev/null
+++ b/ddd-modules/sharedkernel/src/main/java/com/baeldung/dddmodules/sharedkernel/service/ApplicationService.java
@@ -0,0 +1,33 @@
+package com.baeldung.dddmodules.sharedkernel.service;
+
+import com.baeldung.dddmodules.sharedkernel.events.ApplicationEvent;
+import com.baeldung.dddmodules.sharedkernel.events.EventBus;
+import com.baeldung.dddmodules.sharedkernel.events.EventSubscriber;
+
+public interface ApplicationService {
+
+ default void publishEvent(E event) {
+ EventBus eventBus = getEventBus();
+ if (eventBus != null) {
+ eventBus.publish(event);
+ }
+ }
+
+ default void subscribe(String eventType, EventSubscriber subscriber) {
+ EventBus eventBus = getEventBus();
+ if (eventBus != null) {
+ eventBus.subscribe(eventType, subscriber);
+ }
+ }
+
+ default void unsubscribe(String eventType, EventSubscriber subscriber) {
+ EventBus eventBus = getEventBus();
+ if (eventBus != null) {
+ eventBus.unsubscribe(eventType, subscriber);
+ }
+ }
+
+ EventBus getEventBus();
+
+ void setEventBus(EventBus eventBus);
+}
diff --git a/ddd-modules/sharedkernel/src/main/java/module-info.java b/ddd-modules/sharedkernel/src/main/java/module-info.java
new file mode 100644
index 0000000000..aeb64f52c9
--- /dev/null
+++ b/ddd-modules/sharedkernel/src/main/java/module-info.java
@@ -0,0 +1,4 @@
+module com.baeldung.dddmodules.sharedkernel {
+ exports com.baeldung.dddmodules.sharedkernel.events;
+ exports com.baeldung.dddmodules.sharedkernel.service;
+}
diff --git a/ddd-modules/shippingcontext/pom.xml b/ddd-modules/shippingcontext/pom.xml
new file mode 100644
index 0000000000..060f4fe5bf
--- /dev/null
+++ b/ddd-modules/shippingcontext/pom.xml
@@ -0,0 +1,42 @@
+
+
+ 4.0.0
+ com.baeldung.dddmodules.shippingcontext
+ shippingcontext
+ 1.0
+ jar
+
+
+ com.baeldung.dddmodules
+ dddmodules
+ 1.0
+
+
+
+
+ com.baeldung.dddmodules.sharedkernel
+ sharedkernel
+ ${appmodules.version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ ${source.version}
+ ${target.version}
+
+
+
+
+
+
+ 9
+ 9
+
+
+
\ No newline at end of file
diff --git a/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/model/PackageItem.java b/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/model/PackageItem.java
new file mode 100644
index 0000000000..ed09a0f2a2
--- /dev/null
+++ b/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/model/PackageItem.java
@@ -0,0 +1,37 @@
+package com.baeldung.dddmodules.shippingcontext.model;
+
+public class PackageItem {
+ private int productId;
+ private float weight;
+ private float estimatedValue;
+
+ public PackageItem(int productId, float weight, float estimatedValue) {
+ this.productId = productId;
+ this.weight = weight;
+ this.estimatedValue = estimatedValue;
+ }
+
+ public int getProductId() {
+ return productId;
+ }
+
+ public void setProductId(int productId) {
+ this.productId = productId;
+ }
+
+ public float getWeight() {
+ return weight;
+ }
+
+ public void setWeight(float weight) {
+ this.weight = weight;
+ }
+
+ public float getEstimatedValue() {
+ return estimatedValue;
+ }
+
+ public void setEstimatedValue(float estimatedValue) {
+ this.estimatedValue = estimatedValue;
+ }
+}
diff --git a/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/model/Parcel.java b/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/model/Parcel.java
new file mode 100644
index 0000000000..70c4f06ac6
--- /dev/null
+++ b/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/model/Parcel.java
@@ -0,0 +1,54 @@
+package com.baeldung.dddmodules.shippingcontext.model;
+
+import java.util.List;
+
+public class Parcel {
+ private int orderId;
+ private String address;
+ private String trackingId;
+ private List packageItems;
+
+ public Parcel(int orderId, String address, List packageItems) {
+ this.orderId = orderId;
+ this.address = address;
+ this.packageItems = packageItems;
+ }
+
+ public float calculateTotalWeight() {
+ return packageItems.stream().map(PackageItem::getWeight)
+ .reduce(0F, Float::sum);
+ }
+
+ public boolean isTaxable() {
+ return calculateEstimatedValue() > 100;
+ }
+
+ public float calculateEstimatedValue() {
+ return packageItems.stream().map(PackageItem::getWeight)
+ .reduce(0F, Float::sum);
+ }
+
+ public int getOrderId() {
+ return orderId;
+ }
+
+ public void setOrderId(int orderId) {
+ this.orderId = orderId;
+ }
+
+ public String getTrackingId() {
+ return trackingId;
+ }
+
+ public void setTrackingId(String trackingId) {
+ this.trackingId = trackingId;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+}
diff --git a/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/model/ShippableOrder.java b/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/model/ShippableOrder.java
new file mode 100644
index 0000000000..afeea2f472
--- /dev/null
+++ b/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/model/ShippableOrder.java
@@ -0,0 +1,38 @@
+package com.baeldung.dddmodules.shippingcontext.model;
+
+import java.util.List;
+
+public class ShippableOrder {
+ private int orderId;
+ private String address;
+ private List packageItems;
+
+ public ShippableOrder(int orderId, List packageItems) {
+ this.orderId = orderId;
+ this.packageItems = packageItems;
+ }
+
+ public int getOrderId() {
+ return orderId;
+ }
+
+ public void setOrderId(int orderId) {
+ this.orderId = orderId;
+ }
+
+ public List getPackageItems() {
+ return packageItems;
+ }
+
+ public void setPackageItems(List packageItems) {
+ this.packageItems = packageItems;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+}
diff --git a/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/repository/ShippingOrderRepository.java b/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/repository/ShippingOrderRepository.java
new file mode 100644
index 0000000000..b1a643f989
--- /dev/null
+++ b/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/repository/ShippingOrderRepository.java
@@ -0,0 +1,9 @@
+package com.baeldung.dddmodules.shippingcontext.repository;
+
+import com.baeldung.dddmodules.shippingcontext.model.ShippableOrder;
+
+import java.util.Optional;
+
+public interface ShippingOrderRepository {
+ Optional findShippableOrder(int orderId);
+}
diff --git a/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/service/ParcelShippingService.java b/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/service/ParcelShippingService.java
new file mode 100644
index 0000000000..05f261612e
--- /dev/null
+++ b/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/service/ParcelShippingService.java
@@ -0,0 +1,63 @@
+package com.baeldung.dddmodules.shippingcontext.service;
+
+import com.baeldung.dddmodules.sharedkernel.events.ApplicationEvent;
+import com.baeldung.dddmodules.sharedkernel.events.EventBus;
+import com.baeldung.dddmodules.sharedkernel.events.EventSubscriber;
+import com.baeldung.dddmodules.shippingcontext.model.Parcel;
+import com.baeldung.dddmodules.shippingcontext.model.ShippableOrder;
+import com.baeldung.dddmodules.shippingcontext.repository.ShippingOrderRepository;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+public class ParcelShippingService implements ShippingService {
+ public static final String EVENT_ORDER_READY_FOR_SHIPMENT = "OrderReadyForShipmentEvent";
+ private ShippingOrderRepository orderRepository;
+ private EventBus eventBus;
+ private Map shippedParcels = new HashMap<>();
+
+ @Override
+ public void shipOrder(int orderId) {
+ Optional order = this.orderRepository.findShippableOrder(orderId);
+ order.ifPresent(completedOrder -> {
+ Parcel parcel = new Parcel(completedOrder.getOrderId(), completedOrder.getAddress(), completedOrder.getPackageItems());
+ if (parcel.isTaxable()) {
+ // Calculate additional taxes
+ }
+ // Ship parcel
+ this.shippedParcels.put(completedOrder.getOrderId(), parcel);
+ });
+ }
+
+ @Override
+ public void listenToOrderEvents() {
+ this.eventBus.subscribe(EVENT_ORDER_READY_FOR_SHIPMENT, new EventSubscriber() {
+ @Override
+ public void onEvent(E event) {
+ shipOrder(Integer.parseInt(event.getPayloadValue("order_id")));
+ }
+ });
+ }
+
+ @Override
+ public Optional getParcelByOrderId(int orderId) {
+ return Optional.ofNullable(this.shippedParcels.get(orderId));
+ }
+
+ public void setOrderRepository(ShippingOrderRepository orderRepository) {
+ this.orderRepository = orderRepository;
+ }
+
+ @Override
+ public EventBus getEventBus() {
+ return eventBus;
+ }
+
+ @Override
+ public void setEventBus(EventBus eventBus) {
+ this.eventBus = eventBus;
+ }
+
+
+}
diff --git a/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/service/ShippingService.java b/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/service/ShippingService.java
new file mode 100644
index 0000000000..a2f0095c43
--- /dev/null
+++ b/ddd-modules/shippingcontext/src/main/java/com/baeldung/dddmodules/shippingcontext/service/ShippingService.java
@@ -0,0 +1,17 @@
+package com.baeldung.dddmodules.shippingcontext.service;
+
+import com.baeldung.dddmodules.sharedkernel.service.ApplicationService;
+import com.baeldung.dddmodules.shippingcontext.model.Parcel;
+import com.baeldung.dddmodules.shippingcontext.repository.ShippingOrderRepository;
+
+import java.util.Optional;
+
+public interface ShippingService extends ApplicationService {
+ void shipOrder(int orderId);
+
+ void listenToOrderEvents();
+
+ Optional getParcelByOrderId(int orderId);
+
+ void setOrderRepository(ShippingOrderRepository orderRepository);
+}
diff --git a/ddd-modules/shippingcontext/src/main/java/module-info.java b/ddd-modules/shippingcontext/src/main/java/module-info.java
new file mode 100644
index 0000000000..a5ec1ca435
--- /dev/null
+++ b/ddd-modules/shippingcontext/src/main/java/module-info.java
@@ -0,0 +1,8 @@
+module com.baeldung.dddmodules.shippingcontext {
+ requires com.baeldung.dddmodules.sharedkernel;
+ exports com.baeldung.dddmodules.shippingcontext.service;
+ exports com.baeldung.dddmodules.shippingcontext.model;
+ exports com.baeldung.dddmodules.shippingcontext.repository;
+ provides com.baeldung.dddmodules.shippingcontext.service.ShippingService
+ with com.baeldung.dddmodules.shippingcontext.service.ParcelShippingService;
+}
diff --git a/pom.xml b/pom.xml
index 37036193f9..0bcfac7963 100644
--- a/pom.xml
+++ b/pom.xml
@@ -408,6 +408,7 @@
dagger
data-structures
ddd
+
deeplearning4j
disruptor
dozer
@@ -919,6 +920,7 @@
dagger
data-structures
ddd
+
deeplearning4j
disruptor
dozer