diff --git a/algorithms-searching/src/main/java/com/baeldung/algorithms/suffixtree/Node.java b/algorithms-searching/src/main/java/com/baeldung/algorithms/suffixtree/Node.java new file mode 100644 index 0000000000..5a77b09753 --- /dev/null +++ b/algorithms-searching/src/main/java/com/baeldung/algorithms/suffixtree/Node.java @@ -0,0 +1,57 @@ +package com.baeldung.algorithms.suffixtree; + +import java.util.ArrayList; +import java.util.List; + +public class Node { + private String text; + private List children; + private int position; + + public Node(String word, int position) { + this.text = word; + this.position = position; + this.children = new ArrayList<>(); + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public int getPosition() { + return position; + } + + public void setPosition(int position) { + this.position = position; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + public String printTree(String depthIndicator) { + String str = ""; + String positionStr = position > -1 ? "[" + String.valueOf(position) + "]" : ""; + str += depthIndicator + text + positionStr + "\n"; + + for (int i = 0; i < children.size(); i++) { + str += children.get(i) + .printTree(depthIndicator + "\t"); + } + return str; + } + + @Override + public String toString() { + return printTree(""); + } +} \ No newline at end of file diff --git a/algorithms-searching/src/main/java/com/baeldung/algorithms/suffixtree/SuffixTree.java b/algorithms-searching/src/main/java/com/baeldung/algorithms/suffixtree/SuffixTree.java new file mode 100644 index 0000000000..eb58c2bfab --- /dev/null +++ b/algorithms-searching/src/main/java/com/baeldung/algorithms/suffixtree/SuffixTree.java @@ -0,0 +1,175 @@ +package com.baeldung.algorithms.suffixtree; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SuffixTree { + private static final Logger LOGGER = LoggerFactory.getLogger(SuffixTree.class); + private static final String WORD_TERMINATION = "$"; + private static final int POSITION_UNDEFINED = -1; + private Node root; + private String fullText; + + public SuffixTree(String text) { + root = new Node("", POSITION_UNDEFINED); + for (int i = 0; i < text.length(); i++) { + addSuffix(text.substring(i) + WORD_TERMINATION, i); + } + fullText = text; + } + + public List searchText(String pattern) { + LOGGER.info("Searching for pattern \"{}\"", pattern); + List result = new ArrayList<>(); + List nodes = getAllNodesInTraversePath(pattern, root, false); + + if (nodes.size() > 0) { + Node lastNode = nodes.get(nodes.size() - 1); + if (lastNode != null) { + List positions = getPositions(lastNode); + positions = positions.stream() + .sorted() + .collect(Collectors.toList()); + positions.forEach(m -> result.add((markPatternInText(m, pattern)))); + } + } + return result; + } + + private void addSuffix(String suffix, int position) { + LOGGER.info(">>>>>>>>>>>> Adding new suffix {}", suffix); + List nodes = getAllNodesInTraversePath(suffix, root, true); + if (nodes.size() == 0) { + addChildNode(root, suffix, position); + LOGGER.info("{}", printTree()); + } else { + Node lastNode = nodes.remove(nodes.size() - 1); + String newText = suffix; + if (nodes.size() > 0) { + String existingSuffixUptoLastNode = nodes.stream() + .map(a -> a.getText()) + .reduce("", String::concat); + + // Remove prefix from newText already included in parent + newText = newText.substring(existingSuffixUptoLastNode.length()); + } + extendNode(lastNode, newText, position); + LOGGER.info("{}", printTree()); + } + } + + private List getPositions(Node node) { + List positions = new ArrayList<>(); + if (node.getText() + .endsWith(WORD_TERMINATION)) { + positions.add(node.getPosition()); + } + for (int i = 0; i < node.getChildren() + .size(); i++) { + positions.addAll(getPositions(node.getChildren() + .get(i))); + } + return positions; + } + + private String markPatternInText(Integer startPosition, String pattern) { + String matchingTextLHS = fullText.substring(0, startPosition); + String matchingText = fullText.substring(startPosition, startPosition + pattern.length()); + String matchingTextRHS = fullText.substring(startPosition + pattern.length()); + return matchingTextLHS + "[" + matchingText + "]" + matchingTextRHS; + } + + private void addChildNode(Node parentNode, String text, int position) { + parentNode.getChildren() + .add(new Node(text, position)); + } + + private void extendNode(Node node, String newText, int position) { + String currentText = node.getText(); + String commonPrefix = getLongestCommonPrefix(currentText, newText); + + if (commonPrefix != currentText) { + String parentText = currentText.substring(0, commonPrefix.length()); + String childText = currentText.substring(commonPrefix.length()); + splitNodeToParentAndChild(node, parentText, childText); + } + + String remainingText = newText.substring(commonPrefix.length()); + addChildNode(node, remainingText, position); + } + + private void splitNodeToParentAndChild(Node parentNode, String parentNewText, String childNewText) { + Node childNode = new Node(childNewText, parentNode.getPosition()); + + if (parentNode.getChildren() + .size() > 0) { + while (parentNode.getChildren() + .size() > 0) { + childNode.getChildren() + .add(parentNode.getChildren() + .remove(0)); + } + } + + parentNode.getChildren() + .add(childNode); + parentNode.setText(parentNewText); + parentNode.setPosition(POSITION_UNDEFINED); + } + + private String getLongestCommonPrefix(String str1, String str2) { + int compareLength = Math.min(str1.length(), str2.length()); + for (int i = 0; i < compareLength; i++) { + if (str1.charAt(i) != str2.charAt(i)) { + return str1.substring(0, i); + } + } + return str1.substring(0, compareLength); + } + + private List getAllNodesInTraversePath(String pattern, Node startNode, boolean isAllowPartialMatch) { + List nodes = new ArrayList<>(); + for (int i = 0; i < startNode.getChildren() + .size(); i++) { + Node currentNode = startNode.getChildren() + .get(i); + String nodeText = currentNode.getText(); + if (pattern.charAt(0) == nodeText.charAt(0)) { + if (isAllowPartialMatch && pattern.length() <= nodeText.length()) { + nodes.add(currentNode); + return nodes; + } + + int compareLength = Math.min(nodeText.length(), pattern.length()); + for (int j = 1; j < compareLength; j++) { + if (pattern.charAt(j) != nodeText.charAt(j)) { + if (isAllowPartialMatch) { + nodes.add(currentNode); + } + return nodes; + } + } + + nodes.add(currentNode); + if (pattern.length() > compareLength) { + List nodes2 = getAllNodesInTraversePath(pattern.substring(compareLength), currentNode, isAllowPartialMatch); + if (nodes2.size() > 0) { + nodes.addAll(nodes2); + } else if (!isAllowPartialMatch) { + nodes.add(null); + } + } + return nodes; + } + } + return nodes; + } + + public String printTree() { + return root.printTree(""); + } +} diff --git a/algorithms-searching/src/test/java/com/baeldung/algorithms/suffixtree/SuffixTreeUnitTest.java b/algorithms-searching/src/test/java/com/baeldung/algorithms/suffixtree/SuffixTreeUnitTest.java new file mode 100644 index 0000000000..ef4a05a9a1 --- /dev/null +++ b/algorithms-searching/src/test/java/com/baeldung/algorithms/suffixtree/SuffixTreeUnitTest.java @@ -0,0 +1,77 @@ +package com.baeldung.algorithms.suffixtree; + +import java.util.List; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SuffixTreeUnitTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(SuffixTreeUnitTest.class); + + private static SuffixTree suffixTree; + + @BeforeClass + public static void setUp() { + suffixTree = new SuffixTree("havanabanana"); + printTree(); + } + + @Test + public void givenSuffixTree_whenSearchingForA_thenReturn6Matches() { + List matches = suffixTree.searchText("a"); + matches.stream() + .forEach(m -> LOGGER.info(m)); + Assert.assertArrayEquals(new String[] { "h[a]vanabanana", "hav[a]nabanana", "havan[a]banana", "havanab[a]nana", "havanaban[a]na", "havanabanan[a]" }, matches.toArray()); + } + + @Test + public void givenSuffixTree_whenSearchingForNab_thenReturn1Match() { + List matches = suffixTree.searchText("nab"); + matches.stream() + .forEach(m -> LOGGER.info(m)); + Assert.assertArrayEquals(new String[] { "hava[nab]anana" }, matches.toArray()); + } + + @Test + public void givenSuffixTree_whenSearchingForNag_thenReturnNoMatches() { + List matches = suffixTree.searchText("nag"); + matches.stream() + .forEach(m -> LOGGER.info(m)); + Assert.assertArrayEquals(new String[] {}, matches.toArray()); + } + + @Test + public void givenSuffixTree_whenSearchingForBanana_thenReturn2Matches() { + List matches = suffixTree.searchText("ana"); + matches.stream() + .forEach(m -> LOGGER.info(m)); + Assert.assertArrayEquals(new String[] { "hav[ana]banana", "havanab[ana]na", "havanaban[ana]" }, matches.toArray()); + } + + @Test + public void givenSuffixTree_whenSearchingForNa_thenReturn4Matches() { + List matches = suffixTree.searchText("na"); + matches.stream() + .forEach(m -> LOGGER.info(m)); + Assert.assertArrayEquals(new String[] { "hava[na]banana", "havanaba[na]na", "havanabana[na]" }, matches.toArray()); + } + + @Test + public void givenSuffixTree_whenSearchingForX_thenReturnNoMatches() { + List matches = suffixTree.searchText("x"); + matches.stream() + .forEach(m -> LOGGER.info(m)); + Assert.assertArrayEquals(new String[] {}, matches.toArray()); + } + + private static void printTree() { + suffixTree.printTree(); + + LOGGER.info("\n" + suffixTree.printTree()); + LOGGER.info("=============================================="); + } +} diff --git a/core-java-modules/core-java-14/src/main/java/com/baeldung/java14/patternmatchingforinstanceof/PatternMatchingForInstanceOf.java b/core-java-modules/core-java-14/src/main/java/com/baeldung/java14/patternmatchingforinstanceof/PatternMatchingForInstanceOf.java new file mode 100644 index 0000000000..11026f45f9 --- /dev/null +++ b/core-java-modules/core-java-14/src/main/java/com/baeldung/java14/patternmatchingforinstanceof/PatternMatchingForInstanceOf.java @@ -0,0 +1,26 @@ +package com.baeldung.java14.patternmatchingforinstanceof; + +public class PatternMatchingForInstanceOf { + + public void performAnimalOperations(Animal animal) { + if (animal instanceof Cat cat) { + cat.meow(); + } else if(animal instanceof Dog dog) { + dog.woof(); + } + } + + abstract class Animal { + } + + final class Cat extends Animal { + void meow() { + } + } + + final class Dog extends Animal { + void woof() { + } + } + +} diff --git a/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/patternmatchingforinstanceof/PatternMatchingForInstanceOfUnitTest.java b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/patternmatchingforinstanceof/PatternMatchingForInstanceOfUnitTest.java new file mode 100644 index 0000000000..0270e34dec --- /dev/null +++ b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/patternmatchingforinstanceof/PatternMatchingForInstanceOfUnitTest.java @@ -0,0 +1,33 @@ +package com.baeldung.java14.patternmatchingforinstanceof; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import org.junit.jupiter.api.Test; + +import com.baeldung.java14.patternmatchingforinstanceof.PatternMatchingForInstanceOf.Cat; +import com.baeldung.java14.patternmatchingforinstanceof.PatternMatchingForInstanceOf.Dog; + +class PatternMatchingForInstanceOfUnitTest { + + @Test + void givenAnAnimal_whenTypeIsCat_ThenCatGoesMeow() { + Cat animal = mock(Cat.class); + + PatternMatchingForInstanceOf instanceOf = new PatternMatchingForInstanceOf(); + instanceOf.performAnimalOperations(animal); + + verify(animal).meow(); + } + + @Test + void givenAnAnimal_whenTypeIsDog_ThenDogGoesWoof() { + Dog animal = mock(Dog.class); + + PatternMatchingForInstanceOf instanceOf = new PatternMatchingForInstanceOf(); + instanceOf.performAnimalOperations(animal); + + verify(animal).woof(); + } + +} diff --git a/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/suppressed/ExceptionalResource.java b/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/suppressed/ExceptionalResource.java new file mode 100644 index 0000000000..8892e097b1 --- /dev/null +++ b/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/suppressed/ExceptionalResource.java @@ -0,0 +1,13 @@ +package com.baeldung.suppressed; + +public class ExceptionalResource implements AutoCloseable { + + public void processSomething() { + throw new IllegalArgumentException("Thrown from processSomething()"); + } + + @Override + public void close() throws Exception { + throw new NullPointerException("Thrown from close()"); + } +} diff --git a/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/suppressed/SuppressedExceptionsDemo.java b/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/suppressed/SuppressedExceptionsDemo.java new file mode 100644 index 0000000000..6ff23fd041 --- /dev/null +++ b/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/suppressed/SuppressedExceptionsDemo.java @@ -0,0 +1,44 @@ +package com.baeldung.suppressed; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; + +public class SuppressedExceptionsDemo { + + public static void demoSuppressedException(String filePath) throws IOException { + FileInputStream fileIn = null; + try { + fileIn = new FileInputStream(filePath); + } catch (FileNotFoundException e) { + throw new IOException(e); + } finally { + fileIn.close(); + } + } + + public static void demoAddSuppressedException(String filePath) throws IOException { + Throwable firstException = null; + FileInputStream fileIn = null; + try { + fileIn = new FileInputStream(filePath); + } catch (IOException e) { + firstException = e; + } finally { + try { + fileIn.close(); + } catch (NullPointerException npe) { + if (firstException != null) { + npe.addSuppressed(firstException); + } + throw npe; + } + } + } + + public static void demoExceptionalResource() throws Exception { + try (ExceptionalResource exceptionalResource = new ExceptionalResource()) { + exceptionalResource.processSomething(); + } + } +} diff --git a/core-java-modules/core-java-exceptions-2/src/test/java/com/baeldung/suppressed/SuppressedExceptionsUnitTest.java b/core-java-modules/core-java-exceptions-2/src/test/java/com/baeldung/suppressed/SuppressedExceptionsUnitTest.java new file mode 100644 index 0000000000..7664ee6847 --- /dev/null +++ b/core-java-modules/core-java-exceptions-2/src/test/java/com/baeldung/suppressed/SuppressedExceptionsUnitTest.java @@ -0,0 +1,42 @@ +package com.baeldung.suppressed; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import java.io.FileNotFoundException; +import java.io.IOException; + +import org.junit.Test; +import static org.hamcrest.CoreMatchers.instanceOf; + +public class SuppressedExceptionsUnitTest { + + @Test(expected = NullPointerException.class) + public void givenNonExistentFileName_whenAttemptFileOpen_thenNullPointerException() throws IOException { + SuppressedExceptionsDemo.demoSuppressedException("/non-existent-path/non-existent-file.txt"); + } + + @Test + public void givenNonExistentFileName_whenAttemptFileOpenStoreSuppressed_thenSuppressedExceptionAvailable() { + try { + SuppressedExceptionsDemo.demoAddSuppressedException("/non-existent-path/non-existent-file.txt"); + } catch (Exception e) { + assertThat(e, instanceOf(NullPointerException.class)); + assertEquals(1, e.getSuppressed().length); + assertThat(e.getSuppressed()[0], instanceOf(FileNotFoundException.class)); + } + } + + @Test + public void whenUsingExceptionalResource_thenSuppressedExceptionAvailable() { + try { + SuppressedExceptionsDemo.demoExceptionalResource(); + } catch (Exception e) { + assertThat(e, instanceOf(IllegalArgumentException.class)); + assertEquals("Thrown from processSomething()", e.getMessage()); + assertEquals(1, e.getSuppressed().length); + assertThat(e.getSuppressed()[0], instanceOf(NullPointerException.class)); + assertEquals("Thrown from close()", e.getSuppressed()[0].getMessage()); + } + } +} 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/gradle/gradle-to-maven/build.gradle b/gradle/gradle-to-maven/build.gradle new file mode 100644 index 0000000000..110edbc421 --- /dev/null +++ b/gradle/gradle-to-maven/build.gradle @@ -0,0 +1,41 @@ +repositories { + mavenCentral() +} + +apply plugin: 'java' +apply plugin: 'maven' + +group = 'com.baeldung' + +// by default, pom's artifactId is taken from the directory name + +version = '0.0.1-SNAPSHOT' + +dependencies { + compile('org.slf4j:slf4j-api') + testCompile('junit:junit') +} + +install { + repositories { + mavenInstaller { + pom.version = '0.0.1-maven-SNAPSHOT' + pom.groupId = 'com.baeldung.sample' + pom.artifactId = 'gradle-maven-converter' + pom.project { + inceptionYear '2020' + licenses { + license { + name 'My License' + url 'http://www.mycompany.com/licenses/license.txt' + distribution 'repo' + } + } + } + pom.whenConfigured {pom -> + pom.dependencies.find {dep -> dep.groupId == 'junit' && dep.artifactId == 'junit' }.optional = true + } + pom.writeTo("${mavenPomDir}/${project.group}/${project.name}/pom.xml") + } + } +} \ No newline at end of file diff --git a/intelliJ/remote-debugging/.idea/runConfigurations/Remote_Debugger.xml b/intelliJ/remote-debugging/.idea/runConfigurations/Remote_Debugger.xml deleted file mode 100644 index ca11791a08..0000000000 --- a/intelliJ/remote-debugging/.idea/runConfigurations/Remote_Debugger.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - \ No newline at end of file diff --git a/intelliJ/remote-debugging/CONTRIBUTING.adoc b/intelliJ/remote-debugging/CONTRIBUTING.adoc deleted file mode 100644 index a97e428a48..0000000000 --- a/intelliJ/remote-debugging/CONTRIBUTING.adoc +++ /dev/null @@ -1,2 +0,0 @@ -If you have not previously done so, please fill out and -submit the https://cla.pivotal.io/sign/spring[Contributor License Agreement]. \ No newline at end of file diff --git a/intelliJ/remote-debugging/LICENSE.code.txt b/intelliJ/remote-debugging/LICENSE.code.txt deleted file mode 100644 index 4b5cde9fd2..0000000000 --- a/intelliJ/remote-debugging/LICENSE.code.txt +++ /dev/null @@ -1,16 +0,0 @@ - All code in this repository is: - ======================================================================= - Copyright (c) 2013 GoPivotal, Inc. All Rights Reserved - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - diff --git a/intelliJ/remote-debugging/LICENSE.writing.txt b/intelliJ/remote-debugging/LICENSE.writing.txt deleted file mode 100644 index 9d21229f84..0000000000 --- a/intelliJ/remote-debugging/LICENSE.writing.txt +++ /dev/null @@ -1 +0,0 @@ -Except where otherwise noted, this work is licensed under https://creativecommons.org/licenses/by-nd/3.0/ diff --git a/intelliJ/remote-debugging/README.md b/intelliJ/remote-debugging/README.md deleted file mode 100644 index 54e3e00ace..0000000000 --- a/intelliJ/remote-debugging/README.md +++ /dev/null @@ -1,3 +0,0 @@ -### Relevant Articles: - -- [Remote Debugging with IntelliJ IDEA](https://www.baeldung.com/intellij-remote-debugging) diff --git a/intelliJ/remote-debugging/pom.xml b/intelliJ/remote-debugging/pom.xml deleted file mode 100644 index b8845e49d2..0000000000 --- a/intelliJ/remote-debugging/pom.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - 4.0.0 - - com.baeldung - gs-scheduling-tasks - 0.1.0 - gs-scheduling-tasks - - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 - - - - 1.8 - 3.1.2 - 2.1.6.RELEASE - - - - - org.springframework.boot - spring-boot-starter - - - org.springframework.boot - spring-boot-starter-test - test - - - org.awaitility - awaitility - ${awaitility.version} - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - diff --git a/intelliJ/remote-debugging/src/main/java/hello/ScheduledTasks.java b/intelliJ/remote-debugging/src/main/java/hello/ScheduledTasks.java deleted file mode 100644 index de1f6eebeb..0000000000 --- a/intelliJ/remote-debugging/src/main/java/hello/ScheduledTasks.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2012-2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package hello; - -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; - -@Component -public class ScheduledTasks { - - private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class); - - private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); - - @Scheduled(fixedRate = 5000) - public void reportCurrentTime() { - log.info("The time is now {}", dateFormat.format(new Date())); - } -} diff --git a/libraries-3/README.md b/libraries-3/README.md index 942f108afd..404045e6b1 100644 --- a/libraries-3/README.md +++ b/libraries-3/README.md @@ -11,3 +11,4 @@ Remember, for advanced libraries like [Jackson](/jackson) and [JUnit](/testing-m - [Parsing Command-Line Parameters with JCommander](https://www.baeldung.com/jcommander-parsing-command-line-parameters) - [Guide to the Cactoos Library](https://www.baeldung.com/java-cactoos) - [Parsing Command-Line Parameters with Airline](https://www.baeldung.com/java-airline) +- [Introduction to cache2k](https://www.baeldung.com/java-cache2k) diff --git a/lombok-custom/pom.xml b/lombok-custom/pom.xml index 75c3f9d407..220367bfe9 100644 --- a/lombok-custom/pom.xml +++ b/lombok-custom/pom.xml @@ -53,24 +53,6 @@ - - mac-profile - - false - - ${java.home}/../Classes/classes.jar - - - - - com.sun - tools - ${java.version} - system - ${java.home}/../Classes/classes.jar - - - diff --git a/persistence-modules/spring-data-jpa-4/pom.xml b/persistence-modules/spring-data-jpa-4/pom.xml index e0b441231e..8a476012c7 100644 --- a/persistence-modules/spring-data-jpa-4/pom.xml +++ b/persistence-modules/spring-data-jpa-4/pom.xml @@ -23,6 +23,16 @@ spring-boot-starter-data-jpa + + org.springframework.boot + spring-boot-starter-data-jdbc + + + + mysql + mysql-connector-java + + com.h2database h2 diff --git a/intelliJ/remote-debugging/src/main/java/hello/Application.java b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/storedprocedure/StoredProcedureApplication.java similarity index 52% rename from intelliJ/remote-debugging/src/main/java/hello/Application.java rename to persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/storedprocedure/StoredProcedureApplication.java index 73b55f933b..5f05764e21 100644 --- a/intelliJ/remote-debugging/src/main/java/hello/Application.java +++ b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/storedprocedure/StoredProcedureApplication.java @@ -1,14 +1,13 @@ -package hello; +package com.baeldung.storedprocedure; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication -@EnableScheduling -public class Application { +public class StoredProcedureApplication { public static void main(String[] args) { - SpringApplication.run(Application.class); + SpringApplication.run(StoredProcedureApplication.class, args); } + } diff --git a/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/storedprocedure/controller/CarController.java b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/storedprocedure/controller/CarController.java new file mode 100644 index 0000000000..6aef600d01 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/storedprocedure/controller/CarController.java @@ -0,0 +1,47 @@ +package com.baeldung.storedprocedure.controller; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.storedprocedure.entity.Car; +import com.baeldung.storedprocedure.service.CarService; + +@RestController +public class CarController { + @Autowired + private CarService carService; + + @GetMapping(path = "/modelcount") + public long getTotalCarsByModel(@RequestParam("model") String model) { + return carService.getTotalCarsByModel(model); + } + + @GetMapping(path = "/modelcountP") + public long getTotalCarsByModelProcedureName(@RequestParam("model") String model) { + return carService.getTotalCarsByModelProcedureName(model); + } + + @GetMapping(path = "/modelcountV") + public long getTotalCarsByModelVaue(@RequestParam("model") String model) { + return carService.getTotalCarsByModelValue(model); + } + + @GetMapping(path = "/modelcountEx") + public long getTotalCarsByModelExplicit(@RequestParam("model") String model) { + return carService.getTotalCarsByModelExplicit(model); + } + + @GetMapping(path = "/modelcountEn") + public long getTotalCarsByModelEntity(@RequestParam("model") String model) { + return carService.getTotalCarsByModelEntity(model); + } + + @GetMapping(path = "/carsafteryear") + public List findCarsAfterYear(@RequestParam("year") Integer year) { + return carService.findCarsAfterYear(year); + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/storedprocedure/entity/Car.java b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/storedprocedure/entity/Car.java new file mode 100644 index 0000000000..2817c25ff7 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/storedprocedure/entity/Car.java @@ -0,0 +1,41 @@ +package com.baeldung.storedprocedure.entity; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.NamedStoredProcedureQuery; +import javax.persistence.StoredProcedureParameter; +import javax.persistence.ParameterMode; + +@Entity +@NamedStoredProcedureQuery(name = "Car.getTotalCardsbyModelEntity", procedureName = "GET_TOTAL_CARS_BY_MODEL", parameters = { + @StoredProcedureParameter(mode = ParameterMode.IN, name = "model_in", type = String.class), + @StoredProcedureParameter(mode = ParameterMode.OUT, name = "count_out", type = Integer.class) }) + +public class Car { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column + private long id; + + @Column + private String model; + + @Column + private Integer year; + + public long getId() { + return id; + } + + public String getModel() { + return model; + } + + public Integer getYear() { + return year; + } + +} diff --git a/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/storedprocedure/repository/CarRepository.java b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/storedprocedure/repository/CarRepository.java new file mode 100644 index 0000000000..3d9428628e --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/storedprocedure/repository/CarRepository.java @@ -0,0 +1,34 @@ +package com.baeldung.storedprocedure.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.jpa.repository.query.Procedure; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import com.baeldung.storedprocedure.entity.Car; + +@Repository +public interface CarRepository extends JpaRepository { + + @Procedure + int GET_TOTAL_CARS_BY_MODEL(String model); + + @Procedure("GET_TOTAL_CARS_BY_MODEL") + int getTotalCarsByModel(String model); + + @Procedure(procedureName = "GET_TOTAL_CARS_BY_MODEL") + int getTotalCarsByModelProcedureName(String model); + + @Procedure(value = "GET_TOTAL_CARS_BY_MODEL") + int getTotalCarsByModelValue(String model); + + @Procedure(name = "Car.getTotalCardsbyModelEntity") + int getTotalCarsByModelEntiy(@Param("model_in") String model); + + @Query(value = "CALL FIND_CARS_AFTER_YEAR(:year_in);", nativeQuery = true) + List findCarsAfterYear(@Param("year_in") Integer year_in); + +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/storedprocedure/service/CarService.java b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/storedprocedure/service/CarService.java new file mode 100644 index 0000000000..104f46e324 --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/main/java/com/baeldung/storedprocedure/service/CarService.java @@ -0,0 +1,39 @@ +package com.baeldung.storedprocedure.service; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.baeldung.storedprocedure.entity.Car; +import com.baeldung.storedprocedure.repository.CarRepository; + +@Service +public class CarService { + @Autowired + private CarRepository carRepository; + + public int getTotalCarsByModel(String model) { + return carRepository.getTotalCarsByModel(model); + } + + public int getTotalCarsByModelProcedureName(String model) { + return carRepository.getTotalCarsByModelProcedureName(model); + } + + public int getTotalCarsByModelValue(String model) { + return carRepository.getTotalCarsByModelValue(model); + } + + public int getTotalCarsByModelExplicit(String model) { + return carRepository.GET_TOTAL_CARS_BY_MODEL(model); + } + + public int getTotalCarsByModelEntity(String model) { + return carRepository.getTotalCarsByModelEntiy(model); + } + + public List findCarsAfterYear(Integer year) { + return carRepository.findCarsAfterYear(year); + } +} diff --git a/persistence-modules/spring-data-jpa-4/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-4/src/main/resources/application.properties index 72fc330767..d79c23e0c7 100644 --- a/persistence-modules/spring-data-jpa-4/src/main/resources/application.properties +++ b/persistence-modules/spring-data-jpa-4/src/main/resources/application.properties @@ -1 +1,5 @@ -spring.jpa.show-sql=true \ No newline at end of file +spring.jpa.show-sql=true +#MySql +spring.datasource.url=jdbc:mysql://localhost:3306/baeldung +spring.datasource.username=baeldung +spring.datasource.password=baeldung \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-4/src/main/resources/car-mysql.sql b/persistence-modules/spring-data-jpa-4/src/main/resources/car-mysql.sql new file mode 100644 index 0000000000..bb4ab2a86e --- /dev/null +++ b/persistence-modules/spring-data-jpa-4/src/main/resources/car-mysql.sql @@ -0,0 +1,27 @@ +DROP TABLE IF EXISTS car; + +CREATE TABLE car (id int(10) NOT NULL AUTO_INCREMENT, + model varchar(50) NOT NULL, + year int(4) NOT NULL, + PRIMARY KEY (id)); + +INSERT INTO car (model, year) VALUES ('BMW', 2000); +INSERT INTO car (model, year) VALUES ('BENZ', 2010); +INSERT INTO car (model, year) VALUES ('PORCHE', 2005); +INSERT INTO car (model, year) VALUES ('PORCHE', 2004); + +DELIMITER $$ + +DROP PROCEDURE IF EXISTS FIND_CARS_AFTER_YEAR$$ +CREATE PROCEDURE FIND_CARS_AFTER_YEAR(IN year_in INT) +BEGIN + SELECT * FROM car WHERE year >= year_in ORDER BY year; +END$$ + +DROP PROCEDURE IF EXISTS GET_TOTAL_CARS_BY_MODEL$$ +CREATE PROCEDURE GET_TOTAL_CARS_BY_MODEL(IN model_in VARCHAR(50), OUT count_out INT) +BEGIN + SELECT COUNT(*) into count_out from car WHERE model = model_in; +END$$ + +DELIMITER ; diff --git a/pom.xml b/pom.xml index bfc2d27e1e..0bcfac7963 100644 --- a/pom.xml +++ b/pom.xml @@ -408,6 +408,7 @@ dagger data-structures ddd + deeplearning4j disruptor dozer @@ -640,7 +641,7 @@ spring-bom spring-boot-modules spring-boot-rest - + spring-caching spring-cloud @@ -728,6 +729,7 @@ spring-static-resources spring-swagger-codegen + spring-threads spring-thymeleaf spring-thymeleaf-2 @@ -918,6 +920,7 @@ dagger data-structures ddd + deeplearning4j disruptor dozer @@ -1334,7 +1337,7 @@ 2.21.0 - 1.7.21 + 1.7.30 1.1.7 diff --git a/spring-boot-modules/spring-boot-parent/spring-boot-with-custom-parent/pom.xml b/spring-boot-modules/spring-boot-parent/spring-boot-with-custom-parent/pom.xml index 1eb4255c7e..d08384e34c 100644 --- a/spring-boot-modules/spring-boot-parent/spring-boot-with-custom-parent/pom.xml +++ b/spring-boot-modules/spring-boot-parent/spring-boot-with-custom-parent/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../../parent-boot-2 diff --git a/spring-boot-modules/spring-boot-parent/spring-boot-with-starter-parent/pom.xml b/spring-boot-modules/spring-boot-parent/spring-boot-with-starter-parent/pom.xml index 05c61fc4cc..baba410b39 100644 --- a/spring-boot-modules/spring-boot-parent/spring-boot-with-starter-parent/pom.xml +++ b/spring-boot-modules/spring-boot-parent/spring-boot-with-starter-parent/pom.xml @@ -12,7 +12,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../../parent-boot-2 diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/cors/AccountController.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/cors/AccountController.java index c387eb2121..2a4156a392 100644 --- a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/cors/AccountController.java +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/cors/AccountController.java @@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.RestController; public class AccountController { @CrossOrigin("http://example.com") - @RequestMapping("/{id}") + @RequestMapping(method = RequestMethod.GET, path = "/{id}") public Account retrieve(@PathVariable Long id) { return new Account(id); } diff --git a/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/cors/config/WebConfig.java b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/cors/config/WebConfig.java new file mode 100644 index 0000000000..c3179621b7 --- /dev/null +++ b/spring-boot-modules/spring-boot-runtime/src/main/java/com/baeldung/cors/config/WebConfig.java @@ -0,0 +1,16 @@ +package com.baeldung.cors.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +@EnableWebMvc +public class WebConfig implements WebMvcConfigurer { + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**"); + } +} diff --git a/spring-boot-modules/spring-boot-testing/pom.xml b/spring-boot-modules/spring-boot-testing/pom.xml index 8b16b13733..8353f9de61 100644 --- a/spring-boot-modules/spring-boot-testing/pom.xml +++ b/spring-boot-modules/spring-boot-testing/pom.xml @@ -132,7 +132,6 @@ 1.2-groovy-2.4 1.6 0.7.2 - 2.1.9.RELEASE diff --git a/spring-boot-modules/spring-boot-testing/src/test/groovy/com/baeldung/boot/WebControllerTest.groovy b/spring-boot-modules/spring-boot-testing/src/test/groovy/com/baeldung/boot/WebControllerTest.groovy index d8b4e03adc..fe53abd241 100644 --- a/spring-boot-modules/spring-boot-testing/src/test/groovy/com/baeldung/boot/WebControllerTest.groovy +++ b/spring-boot-modules/spring-boot-testing/src/test/groovy/com/baeldung/boot/WebControllerTest.groovy @@ -1,8 +1,10 @@ package com.baeldung.boot import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest +import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.request.MockMvcRequestBuilders import org.springframework.test.web.servlet.result.MockMvcResultMatchers @@ -12,8 +14,9 @@ import spock.lang.Title @Title("WebController Specification") @Narrative("The Specification of the behaviour of the WebController. It can greet a person, change the name and reset it to 'world'") -@AutoConfigureMockMvc(secure=false) -@WebMvcTest() +@SpringBootTest +@AutoConfigureMockMvc +@EnableAutoConfiguration(exclude= SecurityAutoConfiguration.class) class WebControllerTest extends Specification { @Autowired diff --git a/spring-boot-modules/spring-boot/README.MD b/spring-boot-modules/spring-boot/README.MD index 217d9e90b2..d010b96860 100644 --- a/spring-boot-modules/spring-boot/README.MD +++ b/spring-boot-modules/spring-boot/README.MD @@ -31,3 +31,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring Shutdown Callbacks](https://www.baeldung.com/spring-shutdown-callbacks) - [Container Configuration in Spring Boot 2](https://www.baeldung.com/embeddedservletcontainercustomizer-configurableembeddedservletcontainer-spring-boot) - [Validation in Spring Boot](https://www.baeldung.com/spring-boot-bean-validation) +- [The BeanDefinitionOverrideException in Spring Boot](https://www.baeldung.com/spring-boot-bean-definition-override-exception) diff --git a/spring-boot/src/test/java/com/baeldung/beandefinitionoverrideexception/SpringBootBeanDefinitionOverrideExceptionIntegrationTest.java b/spring-boot-modules/spring-boot/src/test/java/com/baeldung/beandefinitionoverrideexception/SpringBootBeanDefinitionOverrideExceptionIntegrationTest.java similarity index 100% rename from spring-boot/src/test/java/com/baeldung/beandefinitionoverrideexception/SpringBootBeanDefinitionOverrideExceptionIntegrationTest.java rename to spring-boot-modules/spring-boot/src/test/java/com/baeldung/beandefinitionoverrideexception/SpringBootBeanDefinitionOverrideExceptionIntegrationTest.java diff --git a/spring-boot/src/test/java/com/baeldung/beandefinitionoverrideexception/TestConfiguration1.java b/spring-boot-modules/spring-boot/src/test/java/com/baeldung/beandefinitionoverrideexception/TestConfiguration1.java similarity index 100% rename from spring-boot/src/test/java/com/baeldung/beandefinitionoverrideexception/TestConfiguration1.java rename to spring-boot-modules/spring-boot/src/test/java/com/baeldung/beandefinitionoverrideexception/TestConfiguration1.java diff --git a/spring-boot/src/test/java/com/baeldung/beandefinitionoverrideexception/TestConfiguration2.java b/spring-boot-modules/spring-boot/src/test/java/com/baeldung/beandefinitionoverrideexception/TestConfiguration2.java similarity index 100% rename from spring-boot/src/test/java/com/baeldung/beandefinitionoverrideexception/TestConfiguration2.java rename to spring-boot-modules/spring-boot/src/test/java/com/baeldung/beandefinitionoverrideexception/TestConfiguration2.java diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java index 8174480078..a09878fb84 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java @@ -4,6 +4,8 @@ import java.util.List; import javax.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Page; @@ -11,6 +13,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -25,6 +28,8 @@ import org.springframework.web.util.UriComponentsBuilder; import com.baeldung.persistence.model.Foo; import com.baeldung.persistence.service.IFooService; +import com.baeldung.web.exception.CustomException1; +import com.baeldung.web.exception.CustomException2; import com.baeldung.web.exception.MyResourceNotFoundException; import com.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent; import com.baeldung.web.hateoas.event.ResourceCreatedEvent; @@ -36,6 +41,8 @@ import com.google.common.base.Preconditions; @RequestMapping(value = "/foos") public class FooController { + private static final Logger logger = LoggerFactory.getLogger(FooController.class); + @Autowired private ApplicationEventPublisher eventPublisher; @@ -137,4 +144,10 @@ public class FooController { public void delete(@PathVariable("id") final Long id) { service.deleteById(id); } + + @ExceptionHandler({ CustomException1.class, CustomException2.class }) + public void handleException(final Exception ex) { + final String error = "Application specific error handling"; + logger.error(error, ex); + } } diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/error/RestResponseStatusExceptionResolver.java b/spring-boot-rest/src/main/java/com/baeldung/web/error/RestResponseStatusExceptionResolver.java new file mode 100644 index 0000000000..6753ab35cf --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/error/RestResponseStatusExceptionResolver.java @@ -0,0 +1,73 @@ +package com.baeldung.web.error; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; + +@Component +public class RestResponseStatusExceptionResolver extends AbstractHandlerExceptionResolver { + + private static final Logger logger = LoggerFactory.getLogger(RestResponseStatusExceptionResolver.class); + + @Override + protected ModelAndView doResolveException(HttpServletRequest request, + HttpServletResponse response, Object handler, Exception ex) { + try { + if (ex instanceof IllegalArgumentException) { + return handleIllegalArgument( + (IllegalArgumentException) ex, request, response, handler); + } + } catch (Exception handlerException) { + logger.warn("Handling of [{}] resulted in Exception", ex.getClass().getName(), handlerException); + } + return null; + } + + private ModelAndView handleIllegalArgument(IllegalArgumentException ex, + final HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + final String accept = request.getHeader(HttpHeaders.ACCEPT); + + response.sendError(HttpServletResponse.SC_CONFLICT); + response.setHeader("ContentType", accept); + + final ModelAndView modelAndView = new ModelAndView("error"); + modelAndView.addObject("error", prepareErrorResponse(accept)); + return modelAndView; + } + + /** Prepares error object based on the provided accept type. + * @param accept The Accept header present in the request. + * @return The response to return + * @throws JsonProcessingException + */ + private String prepareErrorResponse(String accept) throws JsonProcessingException { + final Map error = new HashMap<>(); + error.put("Error", "Application specific error message"); + + final String response; + if(MediaType.APPLICATION_JSON_VALUE.equals(accept)) { + response = new ObjectMapper().writeValueAsString(error); + } else { + response = new XmlMapper().writeValueAsString(error); + } + + return response; + } + + + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/exception/CustomException1.java b/spring-boot-rest/src/main/java/com/baeldung/web/exception/CustomException1.java new file mode 100644 index 0000000000..ed8d34ae2b --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/exception/CustomException1.java @@ -0,0 +1,7 @@ +package com.baeldung.web.exception; + +public class CustomException1 extends RuntimeException { + + private static final long serialVersionUID = 1L; + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/exception/CustomException2.java b/spring-boot-rest/src/main/java/com/baeldung/web/exception/CustomException2.java new file mode 100644 index 0000000000..39b6c98a82 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/exception/CustomException2.java @@ -0,0 +1,7 @@ +package com.baeldung.web.exception; + +public class CustomException2 extends RuntimeException { + + private static final long serialVersionUID = 1L; + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java b/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java index fd002efc28..59bcfde57a 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java @@ -1,5 +1,9 @@ package com.baeldung.web.exception; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(value = HttpStatus.NOT_FOUND) public final class MyResourceNotFoundException extends RuntimeException { public MyResourceNotFoundException() { diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java index bd98523b0a..4d4a274b1a 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java @@ -10,8 +10,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import java.util.Collections; import org.hamcrest.Matchers; +import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -24,6 +26,7 @@ import org.springframework.test.web.servlet.MockMvc; import com.baeldung.persistence.model.Foo; import com.baeldung.persistence.service.IFooService; import com.baeldung.web.controller.FooController; +import com.baeldung.web.exception.CustomException1; import com.baeldung.web.hateoas.event.PaginatedResultsRetrievedEvent; /** @@ -56,5 +59,15 @@ public class FooControllerWebLayerIntegrationTest { .andExpect(status().isOk()) .andExpect(jsonPath("$",Matchers.hasSize(1))); } - + + @Test + public void delete_forException_fromService() throws Exception { + Mockito.when(service.findAll()).thenThrow(new CustomException1()); + this.mockMvc.perform(get("/foos")).andDo(h -> { + final Exception expectedException = h.getResolvedException(); + Assert.assertTrue(expectedException instanceof CustomException1); + + }); + } + } diff --git a/spring-cloud/pom.xml b/spring-cloud/pom.xml index 23ad11b03f..c4e606e190 100644 --- a/spring-cloud/pom.xml +++ b/spring-cloud/pom.xml @@ -35,7 +35,7 @@ spring-cloud-archaius spring-cloud-functions spring-cloud-vault - + spring-cloud-security spring-cloud-task spring-cloud-zuul spring-cloud-zuul-fallback diff --git a/spring-cloud/spring-cloud-security/auth-client/src/test/java/org/baeldung/SpringContextTest.java b/spring-cloud/spring-cloud-security/auth-client/src/test/java/com/baeldung/SpringContextTest.java similarity index 94% rename from spring-cloud/spring-cloud-security/auth-client/src/test/java/org/baeldung/SpringContextTest.java rename to spring-cloud/spring-cloud-security/auth-client/src/test/java/com/baeldung/SpringContextTest.java index 02c429acf5..33e5530667 100644 --- a/spring-cloud/spring-cloud-security/auth-client/src/test/java/org/baeldung/SpringContextTest.java +++ b/spring-cloud/spring-cloud-security/auth-client/src/test/java/com/baeldung/SpringContextTest.java @@ -1,4 +1,4 @@ -package org.baeldung; +package com.baeldung; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-cloud/spring-cloud-security/auth-client/src/test/java/com/example/springoath2/Springoath2ApplicationIntegrationTest.java b/spring-cloud/spring-cloud-security/auth-client/src/test/java/com/baeldung/example/springoath2/Springoath2ApplicationIntegrationTest.java similarity index 90% rename from spring-cloud/spring-cloud-security/auth-client/src/test/java/com/example/springoath2/Springoath2ApplicationIntegrationTest.java rename to spring-cloud/spring-cloud-security/auth-client/src/test/java/com/baeldung/example/springoath2/Springoath2ApplicationIntegrationTest.java index 37cff095db..1c5198125e 100644 --- a/spring-cloud/spring-cloud-security/auth-client/src/test/java/com/example/springoath2/Springoath2ApplicationIntegrationTest.java +++ b/spring-cloud/spring-cloud-security/auth-client/src/test/java/com/baeldung/example/springoath2/Springoath2ApplicationIntegrationTest.java @@ -1,4 +1,4 @@ -package com.example.springoath2; +package com.baeldung.example.springoath2; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-cloud/spring-cloud-security/auth-resource/src/test/java/org/baeldung/SpringContextTest.java b/spring-cloud/spring-cloud-security/auth-resource/src/test/java/com/baeldung/SpringContextTest.java similarity index 94% rename from spring-cloud/spring-cloud-security/auth-resource/src/test/java/org/baeldung/SpringContextTest.java rename to spring-cloud/spring-cloud-security/auth-resource/src/test/java/com/baeldung/SpringContextTest.java index a061928bf5..cce93f2c3e 100644 --- a/spring-cloud/spring-cloud-security/auth-resource/src/test/java/org/baeldung/SpringContextTest.java +++ b/spring-cloud/spring-cloud-security/auth-resource/src/test/java/com/baeldung/SpringContextTest.java @@ -1,4 +1,4 @@ -package org.baeldung; +package com.baeldung; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-cloud/spring-cloud-security/auth-server/src/test/java/org/baeldung/SpringContextTest.java b/spring-cloud/spring-cloud-security/auth-server/src/test/java/com/baeldung/SpringContextTest.java similarity index 94% rename from spring-cloud/spring-cloud-security/auth-server/src/test/java/org/baeldung/SpringContextTest.java rename to spring-cloud/spring-cloud-security/auth-server/src/test/java/com/baeldung/SpringContextTest.java index aec56a574c..d61a9c279f 100644 --- a/spring-cloud/spring-cloud-security/auth-server/src/test/java/org/baeldung/SpringContextTest.java +++ b/spring-cloud/spring-cloud-security/auth-server/src/test/java/com/baeldung/SpringContextTest.java @@ -1,4 +1,4 @@ -package org.baeldung; +package com.baeldung; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/singleton/CounterEJB.java b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/singleton/CounterEJB.java deleted file mode 100644 index b64005aed8..0000000000 --- a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/singleton/CounterEJB.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.baeldung.ejb.spring.comparison.ejb.singleton; - -import javax.ejb.Singleton; - -@Singleton -public class CounterEJB implements CounterEJBRemote { - - private int count = 1; - - public int count() { - return count++; - } - -} \ No newline at end of file diff --git a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/singleton/CounterEJBRemote.java b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/singleton/CounterEJBRemote.java deleted file mode 100644 index ec3b9e9f6b..0000000000 --- a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/singleton/CounterEJBRemote.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.ejb.spring.comparison.ejb.singleton; - -import javax.ejb.Remote; - -@Remote -public interface CounterEJBRemote { - int count(); -} diff --git a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/spring/singleton/CounterBean.java b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/spring/singleton/CounterBean.java deleted file mode 100644 index 6456cfc007..0000000000 --- a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/spring/singleton/CounterBean.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.ejb.spring.comparison.spring.singleton; - -import org.springframework.stereotype.Component; - -@Component -public class CounterBean { - private int count = 1; - - public int count() { - return count++; - } -} diff --git a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/messagedriven/RecieverMDB.java b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/messagedriven/RecieverMDB.java similarity index 96% rename from spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/messagedriven/RecieverMDB.java rename to spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/messagedriven/RecieverMDB.java index 7a6b750ce5..f7f43244d5 100644 --- a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/messagedriven/RecieverMDB.java +++ b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/messagedriven/RecieverMDB.java @@ -1,4 +1,4 @@ -package com.baeldung.ejb.spring.comparison.ejb.messagedriven; +package com.baeldung.ejbspringcomparison.ejb.messagedriven; import javax.annotation.Resource; import javax.ejb.ActivationConfigProperty; diff --git a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/singleton/CounterEJB.java b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/singleton/CounterEJB.java new file mode 100644 index 0000000000..6873a717a9 --- /dev/null +++ b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/singleton/CounterEJB.java @@ -0,0 +1,23 @@ +package com.baeldung.ejbspringcomparison.ejb.singleton; + +import javax.ejb.Singleton; + +@Singleton +public class CounterEJB implements CounterEJBRemote { + + private int count = 1; + private String name; + + public int count() { + return count++; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} \ No newline at end of file diff --git a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/singleton/CounterEJBRemote.java b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/singleton/CounterEJBRemote.java new file mode 100644 index 0000000000..ed02cfed4c --- /dev/null +++ b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/singleton/CounterEJBRemote.java @@ -0,0 +1,10 @@ +package com.baeldung.ejbspringcomparison.ejb.singleton; + +import javax.ejb.Remote; + +@Remote +public interface CounterEJBRemote { + int count(); + String getName(); + void setName(String name); +} diff --git a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/stateful/ShoppingCartEJB.java b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/stateful/ShoppingCartEJB.java similarity index 67% rename from spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/stateful/ShoppingCartEJB.java rename to spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/stateful/ShoppingCartEJB.java index 5bdccea994..e01e53add1 100644 --- a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/stateful/ShoppingCartEJB.java +++ b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/stateful/ShoppingCartEJB.java @@ -1,4 +1,4 @@ -package com.baeldung.ejb.spring.comparison.ejb.stateful; +package com.baeldung.ejbspringcomparison.ejb.stateful; import java.util.ArrayList; import java.util.List; @@ -7,7 +7,7 @@ import javax.ejb.Stateful; @Stateful public class ShoppingCartEJB implements ShoppingCartEJBRemote { - + private String name; private List shoppingCart; public ShoppingCartEJB() { @@ -22,4 +22,11 @@ public class ShoppingCartEJB implements ShoppingCartEJBRemote { return shoppingCart; } + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } } diff --git a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/stateful/ShoppingCartEJBRemote.java b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/stateful/ShoppingCartEJBRemote.java similarity index 58% rename from spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/stateful/ShoppingCartEJBRemote.java rename to spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/stateful/ShoppingCartEJBRemote.java index a8d7a15d25..cea9cc3ad9 100644 --- a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/stateful/ShoppingCartEJBRemote.java +++ b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/stateful/ShoppingCartEJBRemote.java @@ -1,4 +1,4 @@ -package com.baeldung.ejb.spring.comparison.ejb.stateful; +package com.baeldung.ejbspringcomparison.ejb.stateful; import java.util.List; @@ -10,4 +10,8 @@ public interface ShoppingCartEJBRemote { void addItem(String item); List getItems(); + + void setName(String name); + + String getName(); } diff --git a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/stateless/FinderEJB.java b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/stateless/FinderEJB.java similarity index 89% rename from spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/stateless/FinderEJB.java rename to spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/stateless/FinderEJB.java index fb45e4e7ce..7609b17675 100644 --- a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/stateless/FinderEJB.java +++ b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/stateless/FinderEJB.java @@ -1,4 +1,4 @@ -package com.baeldung.ejb.spring.comparison.ejb.stateless; +package com.baeldung.ejbspringcomparison.ejb.stateless; import java.util.HashMap; import java.util.Map; diff --git a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/stateless/FinderEJBRemote.java b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/stateless/FinderEJBRemote.java similarity index 65% rename from spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/stateless/FinderEJBRemote.java rename to spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/stateless/FinderEJBRemote.java index 36b4c9ae04..0354eff2b8 100644 --- a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/ejb/stateless/FinderEJBRemote.java +++ b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/ejb/stateless/FinderEJBRemote.java @@ -1,4 +1,4 @@ -package com.baeldung.ejb.spring.comparison.ejb.stateless; +package com.baeldung.ejbspringcomparison.ejb.stateless; import javax.ejb.Remote; diff --git a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/spring/config/ApplicationConfig.java b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/spring/config/ApplicationConfig.java similarity index 89% rename from spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/spring/config/ApplicationConfig.java rename to spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/spring/config/ApplicationConfig.java index 6ec14dc098..8d6114d1c5 100644 --- a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/spring/config/ApplicationConfig.java +++ b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/spring/config/ApplicationConfig.java @@ -1,4 +1,4 @@ -package com.baeldung.ejb.spring.comparison.spring.config; +package com.baeldung.ejbspringcomparison.spring.config; import javax.jms.ConnectionFactory; @@ -11,7 +11,7 @@ import org.springframework.jms.config.DefaultJmsListenerContainerFactory; import org.springframework.jms.core.JmsTemplate; @Configuration -@ComponentScan(basePackages = "com.baeldung.ejb.spring.comparison.spring") +@ComponentScan(basePackages = "com.baeldung.ejbspringcomparison.spring") @EnableJms public class ApplicationConfig { diff --git a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/spring/messagedriven/Producer.java b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/spring/messagedriven/Producer.java similarity index 88% rename from spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/spring/messagedriven/Producer.java rename to spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/spring/messagedriven/Producer.java index a60dc4db8e..683ae7f51b 100644 --- a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/spring/messagedriven/Producer.java +++ b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/spring/messagedriven/Producer.java @@ -1,4 +1,4 @@ -package com.baeldung.ejb.spring.comparison.spring.messagedriven; +package com.baeldung.ejbspringcomparison.spring.messagedriven; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jms.core.JmsTemplate; diff --git a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/spring/messagedriven/Receiver.java b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/spring/messagedriven/Receiver.java similarity index 88% rename from spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/spring/messagedriven/Receiver.java rename to spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/spring/messagedriven/Receiver.java index a3b36dd587..9a483e23c9 100644 --- a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/spring/messagedriven/Receiver.java +++ b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/spring/messagedriven/Receiver.java @@ -1,4 +1,4 @@ -package com.baeldung.ejb.spring.comparison.spring.messagedriven; +package com.baeldung.ejbspringcomparison.spring.messagedriven; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jms.annotation.JmsListener; diff --git a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/spring/singleton/CounterBean.java b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/spring/singleton/CounterBean.java new file mode 100644 index 0000000000..6b2b57582d --- /dev/null +++ b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/spring/singleton/CounterBean.java @@ -0,0 +1,22 @@ +package com.baeldung.ejbspringcomparison.spring.singleton; + +import org.springframework.stereotype.Component; + +@Component +public class CounterBean { + private int count = 1; + private String name; + + public int count() { + return count++; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/spring/stateful/ShoppingCartBean.java b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/spring/stateful/ShoppingCartBean.java similarity index 74% rename from spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/spring/stateful/ShoppingCartBean.java rename to spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/spring/stateful/ShoppingCartBean.java index 9286ff9950..e6e026f52a 100644 --- a/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejb/spring/comparison/spring/stateful/ShoppingCartBean.java +++ b/spring-ejb/ejb-beans/src/main/java/com/baeldung/ejbspringcomparison/spring/stateful/ShoppingCartBean.java @@ -1,4 +1,4 @@ -package com.baeldung.ejb.spring.comparison.spring.stateful; +package com.baeldung.ejbspringcomparison.spring.stateful; import java.util.ArrayList; import java.util.List; @@ -11,6 +11,7 @@ import org.springframework.stereotype.Component; @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class ShoppingCartBean { + private String name; private List shoppingCart; public ShoppingCartBean() { @@ -25,4 +26,11 @@ public class ShoppingCartBean { return shoppingCart; } + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } } diff --git a/spring-ejb/ejb-beans/src/test/java/com/baeldung/ejb/spring/comparison/ejb/EJBUnitTest.java b/spring-ejb/ejb-beans/src/test/java/com/baeldung/ejbspringcomparison/ejb/EJBUnitTest.java similarity index 69% rename from spring-ejb/ejb-beans/src/test/java/com/baeldung/ejb/spring/comparison/ejb/EJBUnitTest.java rename to spring-ejb/ejb-beans/src/test/java/com/baeldung/ejbspringcomparison/ejb/EJBUnitTest.java index 1f0f1bf8a4..069028253e 100644 --- a/spring-ejb/ejb-beans/src/test/java/com/baeldung/ejb/spring/comparison/ejb/EJBUnitTest.java +++ b/spring-ejb/ejb-beans/src/test/java/com/baeldung/ejbspringcomparison/ejb/EJBUnitTest.java @@ -1,9 +1,7 @@ -package com.baeldung.ejb.spring.comparison.ejb; +package com.baeldung.ejbspringcomparison.ejb; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; -import static org.junit.Assert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import javax.annotation.Resource; import javax.ejb.EJB; @@ -25,9 +23,9 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import com.baeldung.ejb.spring.comparison.ejb.singleton.CounterEJBRemote; -import com.baeldung.ejb.spring.comparison.ejb.stateful.ShoppingCartEJBRemote; -import com.baeldung.ejb.spring.comparison.ejb.stateless.FinderEJBRemote; +import com.baeldung.ejbspringcomparison.ejb.singleton.CounterEJBRemote; +import com.baeldung.ejbspringcomparison.ejb.stateful.ShoppingCartEJBRemote; +import com.baeldung.ejbspringcomparison.ejb.stateless.FinderEJBRemote; public class EJBUnitTest { @@ -51,7 +49,7 @@ public class EJBUnitTest { public static void start() throws NamingException { ejbContainer = EJBContainer.createEJBContainer(); } - + @Before public void initializeContext() throws NamingException { context = ejbContainer.getContext(); @@ -60,42 +58,44 @@ public class EJBUnitTest { @Test public void givenSingletonBean_whenCounterInvoked_thenCountIsIncremented() throws NamingException { - + int count = 0; - CounterEJBRemote counterEJB = (CounterEJBRemote) context.lookup("java:global/ejb-beans/CounterEJB"); + CounterEJBRemote firstCounter = (CounterEJBRemote) context.lookup("java:global/ejb-beans/CounterEJB"); + firstCounter.setName("first"); - for (int i = 0; i < 10; i++) - count = counterEJB.count(); - - assertThat(count, is(not(1))); - } - - @Test - public void givenSingletonBean_whenCounterInvokedAgain_thenCountIsIncremented() throws NamingException { - - CounterEJBRemote counterEJB = (CounterEJBRemote) context.lookup("java:global/ejb-beans/CounterEJB"); + for (int i = 0; i < 10; i++) { + count = firstCounter.count(); + } - int count = 0; - for (int i = 0; i < 10; i++) - count = counterEJB.count(); + assertEquals(10, count); + assertEquals("first", firstCounter.getName()); + + CounterEJBRemote secondCounter = (CounterEJBRemote) context.lookup("java:global/ejb-beans/CounterEJB"); + + int count2 = 0; + for (int i = 0; i < 10; i++) { + count2 = secondCounter.count(); + } + + assertEquals(20, count2); + assertEquals("first", secondCounter.getName()); - assertThat(count, is(not(1))); } @Test public void givenStatefulBean_whenBathingCartWithThreeItemsAdded_thenItemsSizeIsThree() throws NamingException { ShoppingCartEJBRemote bathingCart = (ShoppingCartEJBRemote) context.lookup("java:global/ejb-beans/ShoppingCartEJB"); + bathingCart.setName("bathingCart"); + bathingCart.addItem("soap"); bathingCart.addItem("shampoo"); bathingCart.addItem("oil"); assertEquals(3, bathingCart.getItems() .size()); - } + assertEquals("bathingCart", bathingCart.getName()); - @Test - public void givenStatefulBean_whenFruitCartWithTwoItemsAdded_thenItemsSizeIsTwo() throws NamingException { ShoppingCartEJBRemote fruitCart = (ShoppingCartEJBRemote) context.lookup("java:global/ejb-beans/ShoppingCartEJB"); fruitCart.addItem("apples"); @@ -103,6 +103,7 @@ public class EJBUnitTest { assertEquals(2, fruitCart.getItems() .size()); + assertNull(fruitCart.getName()); } @Test @@ -131,10 +132,7 @@ public class EJBUnitTest { } @AfterClass - public static void checkTotalCountAndcloseContext() throws NamingException { - CounterEJBRemote counterEJB = (CounterEJBRemote) context.lookup("java:global/ejb-beans/CounterEJB"); - assertEquals(21, counterEJB.count()); - + public static void closeContext() throws NamingException { context.close(); ejbContainer.close(); } diff --git a/spring-ejb/ejb-beans/src/test/java/com/baeldung/ejb/spring/comparison/spring/SpringUnitTest.java b/spring-ejb/ejb-beans/src/test/java/com/baeldung/ejbspringcomparison/spring/SpringUnitTest.java similarity index 61% rename from spring-ejb/ejb-beans/src/test/java/com/baeldung/ejb/spring/comparison/spring/SpringUnitTest.java rename to spring-ejb/ejb-beans/src/test/java/com/baeldung/ejbspringcomparison/spring/SpringUnitTest.java index a346baba38..e0b397befe 100644 --- a/spring-ejb/ejb-beans/src/test/java/com/baeldung/ejb/spring/comparison/spring/SpringUnitTest.java +++ b/spring-ejb/ejb-beans/src/test/java/com/baeldung/ejbspringcomparison/spring/SpringUnitTest.java @@ -1,9 +1,7 @@ -package com.baeldung.ejb.spring.comparison.spring; +package com.baeldung.ejbspringcomparison.spring; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.not; -import static org.junit.Assert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import javax.naming.NamingException; @@ -15,10 +13,10 @@ import org.junit.ClassRule; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import com.baeldung.ejb.spring.comparison.spring.config.ApplicationConfig; -import com.baeldung.ejb.spring.comparison.spring.messagedriven.Producer; -import com.baeldung.ejb.spring.comparison.spring.singleton.CounterBean; -import com.baeldung.ejb.spring.comparison.spring.stateful.ShoppingCartBean; +import com.baeldung.ejbspringcomparison.spring.config.ApplicationConfig; +import com.baeldung.ejbspringcomparison.spring.messagedriven.Producer; +import com.baeldung.ejbspringcomparison.spring.singleton.CounterBean; +import com.baeldung.ejbspringcomparison.spring.stateful.ShoppingCartBean; public class SpringUnitTest { @@ -46,40 +44,44 @@ public class SpringUnitTest { @Test public void whenCounterInvoked_thenCountIsIncremented() throws NamingException { - CounterBean counterBean = context.getBean(CounterBean.class); + CounterBean firstCounter = context.getBean(CounterBean.class); + firstCounter.setName("first"); int count = 0; - for (int i = 0; i < 10; i++) - count = counterBean.count(); + for (int i = 0; i < 10; i++) { + count = firstCounter.count(); + } - assertThat(count, is(not(1))); - } + assertEquals(10, count); + assertEquals("first", firstCounter.getName()); - @Test - public void whenCounterInvokedAgain_thenCountIsIncremented() throws NamingException { - CounterBean counterBean = context.getBean(CounterBean.class); + CounterBean secondCounter = context.getBean(CounterBean.class); - int count = 0; - for (int i = 0; i < 10; i++) - count = counterBean.count(); + int count2 = 0; + for (int i = 0; i < 10; i++) { + count2 = secondCounter.count(); + } + + assertEquals(20, count2); + assertEquals("first", secondCounter.getName()); - assertThat(count, is(not(1))); } @Test public void whenBathingCartWithThreeItemsAdded_thenItemsSizeIsThree() throws NamingException { ShoppingCartBean bathingCart = context.getBean(ShoppingCartBean.class); + bathingCart.setName("bathingCart"); + bathingCart.addItem("soap"); bathingCart.addItem("shampoo"); bathingCart.addItem("oil"); assertEquals(3, bathingCart.getItems() .size()); - } - @Test - public void whenFruitCartWithTwoItemsAdded_thenItemsSizeIsTwo() throws NamingException { + assertEquals("bathingCart", bathingCart.getName()); + ShoppingCartBean fruitCart = context.getBean(ShoppingCartBean.class); fruitCart.addItem("apples"); @@ -87,6 +89,7 @@ public class SpringUnitTest { assertEquals(2, fruitCart.getItems() .size()); + assertNull(fruitCart.getName()); } @Test @@ -98,10 +101,7 @@ public class SpringUnitTest { } @AfterClass - public static void checkTotalCountAndcloseContext() throws NamingException { - CounterBean counterBean = context.getBean(CounterBean.class); - int count = counterBean.count(); - assertEquals(21, count); + public static void closeContext() throws NamingException { context.close(); } diff --git a/spring-jooq/pom.xml b/spring-jooq/pom.xml index f3b8cce8dc..63c6b5c8ee 100644 --- a/spring-jooq/pom.xml +++ b/spring-jooq/pom.xml @@ -36,6 +36,7 @@ com.h2database h2 + ${h2.version} @@ -194,7 +195,6 @@ 1.5 1.0.0 org.jooq.example.spring.Application - 2.1.9.RELEASE \ No newline at end of file diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java index b313eafdb9..fde56bebc0 100644 --- a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java +++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java @@ -25,7 +25,7 @@ public class KafkaApplication { public static void main(String[] args) throws Exception { ConfigurableApplicationContext context = SpringApplication.run(KafkaApplication.class, args); - + MessageProducer producer = context.getBean(MessageProducer.class); MessageListener listener = context.getBean(MessageListener.class); /* @@ -101,15 +101,17 @@ public class KafkaApplication { private String greetingTopicName; public void sendMessage(String message) { - + ListenableFuture> future = kafkaTemplate.send(topicName, message); - + future.addCallback(new ListenableFutureCallback>() { @Override public void onSuccess(SendResult result) { - System.out.println("Sent message=[" + message + "] with offset=[" + result.getRecordMetadata().offset() + "]"); + System.out.println("Sent message=[" + message + "] with offset=[" + result.getRecordMetadata() + .offset() + "]"); } + @Override public void onFailure(Throwable ex) { System.out.println("Unable to send message=[" + message + "] due to : " + ex.getMessage()); @@ -158,7 +160,7 @@ public class KafkaApplication { latch.countDown(); } - @KafkaListener(topicPartitions = @TopicPartition(topic = "${partitioned.topic.name}", partitions = { "0", "3" })) + @KafkaListener(topicPartitions = @TopicPartition(topic = "${partitioned.topic.name}", partitions = { "0", "3" }), containerFactory = "partitionsKafkaListenerContainerFactory") public void listenToParition(@Payload String message, @Header(KafkaHeaders.RECEIVED_PARTITION_ID) int partition) { System.out.println("Received Message: " + message + " from partition: " + partition); this.partitionLatch.countDown(); diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java index 933d2353aa..abaa431eec 100644 --- a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java +++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java @@ -29,7 +29,7 @@ public class KafkaConsumerConfig { props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); return new DefaultKafkaConsumerFactory<>(props); } - + public ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory(String groupId) { ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>(); factory.setConsumerFactory(consumerFactory(groupId)); @@ -50,12 +50,12 @@ public class KafkaConsumerConfig { public ConcurrentKafkaListenerContainerFactory headersKafkaListenerContainerFactory() { return kafkaListenerContainerFactory("headers"); } - + @Bean public ConcurrentKafkaListenerContainerFactory partitionsKafkaListenerContainerFactory() { return kafkaListenerContainerFactory("partitions"); } - + @Bean public ConcurrentKafkaListenerContainerFactory filterKafkaListenerContainerFactory() { ConcurrentKafkaListenerContainerFactory factory = kafkaListenerContainerFactory("filter"); diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaProducerConfig.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaProducerConfig.java index 7e2527b36e..0223bab0fe 100644 --- a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaProducerConfig.java +++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaProducerConfig.java @@ -32,7 +32,7 @@ public class KafkaProducerConfig { public KafkaTemplate kafkaTemplate() { return new KafkaTemplate<>(producerFactory()); } - + @Bean public ProducerFactory greetingProducerFactory() { Map configProps = new HashMap<>(); @@ -41,10 +41,10 @@ public class KafkaProducerConfig { configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class); return new DefaultKafkaProducerFactory<>(configProps); } - + @Bean public KafkaTemplate greetingKafkaTemplate() { return new KafkaTemplate<>(greetingProducerFactory()); } - + } diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaTopicConfig.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaTopicConfig.java index a3426e78a3..fb60fadde4 100644 --- a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaTopicConfig.java +++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaTopicConfig.java @@ -12,10 +12,10 @@ import org.springframework.kafka.core.KafkaAdmin; @Configuration public class KafkaTopicConfig { - + @Value(value = "${kafka.bootstrapAddress}") private String bootstrapAddress; - + @Value(value = "${message.topic.name}") private String topicName; @@ -27,31 +27,31 @@ public class KafkaTopicConfig { @Value(value = "${greeting.topic.name}") private String greetingTopicName; - + @Bean public KafkaAdmin kafkaAdmin() { Map configs = new HashMap<>(); configs.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress); return new KafkaAdmin(configs); } - + @Bean public NewTopic topic1() { - return new NewTopic(topicName, 1, (short) 1); + return new NewTopic(topicName, 1, (short) 1); } - + @Bean public NewTopic topic2() { - return new NewTopic(partionedTopicName, 6, (short) 1); + return new NewTopic(partionedTopicName, 6, (short) 1); } - + @Bean public NewTopic topic3() { - return new NewTopic(filteredTopicName, 1, (short) 1); + return new NewTopic(filteredTopicName, 1, (short) 1); } - + @Bean public NewTopic topic4() { - return new NewTopic(greetingTopicName, 1, (short) 1); + return new NewTopic(greetingTopicName, 1, (short) 1); } } diff --git a/spring-rest-http/src/main/java/com/baeldung/config/MvcConfig.java b/spring-rest-http/src/main/java/com/baeldung/config/MvcConfig.java index ea2c536757..6e8b41bbed 100644 --- a/spring-rest-http/src/main/java/com/baeldung/config/MvcConfig.java +++ b/spring-rest-http/src/main/java/com/baeldung/config/MvcConfig.java @@ -21,7 +21,7 @@ import java.util.List; */ @Configuration @EnableWebMvc -@ComponentScan({ "com.baeldung.web", "com.baeldung.requestmapping" }) +@ComponentScan({ "com.baeldung.web.controller.status", "com.baeldung.requestmapping" }) public class MvcConfig implements WebMvcConfigurer { public MvcConfig() { diff --git a/spring-rest-http/src/main/java/com/baeldung/web/controller/CustomerRestController.java b/spring-rest-http/src/main/java/com/baeldung/web/controller/customer/CustomerRestController.java similarity index 98% rename from spring-rest-http/src/main/java/com/baeldung/web/controller/CustomerRestController.java rename to spring-rest-http/src/main/java/com/baeldung/web/controller/customer/CustomerRestController.java index 9c248b6d2d..edae10de27 100644 --- a/spring-rest-http/src/main/java/com/baeldung/web/controller/CustomerRestController.java +++ b/spring-rest-http/src/main/java/com/baeldung/web/controller/customer/CustomerRestController.java @@ -1,4 +1,4 @@ -package com.baeldung.web.controller; +package com.baeldung.web.controller.customer; import com.baeldung.model.Customer; import com.baeldung.service.CustomerService; diff --git a/spring-rest-http/src/test/java/com/baeldung/web/controller/CustomerRestControllerIntegrationTest.java b/spring-rest-http/src/test/java/com/baeldung/web/controller/customer/CustomerRestControllerIntegrationTest.java similarity index 98% rename from spring-rest-http/src/test/java/com/baeldung/web/controller/CustomerRestControllerIntegrationTest.java rename to spring-rest-http/src/test/java/com/baeldung/web/controller/customer/CustomerRestControllerIntegrationTest.java index f4d9ff1b92..535bcb1904 100644 --- a/spring-rest-http/src/test/java/com/baeldung/web/controller/CustomerRestControllerIntegrationTest.java +++ b/spring-rest-http/src/test/java/com/baeldung/web/controller/customer/CustomerRestControllerIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.web.controller; +package com.baeldung.web.controller.customer; import com.baeldung.model.Customer; import com.baeldung.service.CustomerService; diff --git a/spring-rest-http/src/test/java/com/baeldung/web/controller/CustomerRestControllerUnitTest.java b/spring-rest-http/src/test/java/com/baeldung/web/controller/customer/CustomerRestControllerUnitTest.java similarity index 99% rename from spring-rest-http/src/test/java/com/baeldung/web/controller/CustomerRestControllerUnitTest.java rename to spring-rest-http/src/test/java/com/baeldung/web/controller/customer/CustomerRestControllerUnitTest.java index d0fb255a5d..6b1293e2c1 100644 --- a/spring-rest-http/src/test/java/com/baeldung/web/controller/CustomerRestControllerUnitTest.java +++ b/spring-rest-http/src/test/java/com/baeldung/web/controller/customer/CustomerRestControllerUnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung.web.controller; +package com.baeldung.web.controller.customer; import com.baeldung.model.Customer; import com.baeldung.service.CustomerService; diff --git a/spring-threads/pom.xml b/spring-threads/pom.xml new file mode 100644 index 0000000000..4513c627b9 --- /dev/null +++ b/spring-threads/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + spring-threads + 0.0.1-SNAPSHOT + spring-threads + jar + + + com.baeldung + parent-spring-5 + 0.0.1-SNAPSHOT + ../parent-spring-5 + + + + + org.springframework + spring-context + ${spring.version} + + + + diff --git a/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java b/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java new file mode 100644 index 0000000000..0d927ebe69 --- /dev/null +++ b/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java @@ -0,0 +1,98 @@ +package com.baeldung.threading; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ThreadLocalRandom; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +public class ThreadPoolTaskExecutorUnitTest { + + void startThreads(ThreadPoolTaskExecutor taskExecutor, CountDownLatch countDownLatch, int numThreads) { + for (int i = 0; i < numThreads; i++) { + taskExecutor.execute(() -> { + try { + Thread.sleep(100L * ThreadLocalRandom.current().nextLong(1, 10)); + countDownLatch.countDown(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + } + } + + @Test + public void whenUsingDefaults_thenSingleThread() { + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.afterPropertiesSet(); + + CountDownLatch countDownLatch = new CountDownLatch(10); + this.startThreads(taskExecutor, countDownLatch, 10); + + while (countDownLatch.getCount() > 0) { + Assert.assertEquals(1, taskExecutor.getPoolSize()); + } + } + + @Test + public void whenCorePoolSizeFive_thenFiveThreads() { + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.setCorePoolSize(5); + taskExecutor.afterPropertiesSet(); + + CountDownLatch countDownLatch = new CountDownLatch(10); + this.startThreads(taskExecutor, countDownLatch, 10); + + while (countDownLatch.getCount() > 0) { + Assert.assertEquals(5, taskExecutor.getPoolSize()); + } + } + + @Test + public void whenCorePoolSizeFiveAndMaxPoolSizeTen_thenFiveThreads() { + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.setCorePoolSize(5); + taskExecutor.setMaxPoolSize(10); + taskExecutor.afterPropertiesSet(); + + CountDownLatch countDownLatch = new CountDownLatch(10); + this.startThreads(taskExecutor, countDownLatch, 10); + + while (countDownLatch.getCount() > 0) { + Assert.assertEquals(5, taskExecutor.getPoolSize()); + } + } + + @Test + public void whenCorePoolSizeFiveAndMaxPoolSizeTenAndQueueCapacityZero_thenTenThreads() { + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.setCorePoolSize(5); + taskExecutor.setMaxPoolSize(10); + taskExecutor.setQueueCapacity(0); + taskExecutor.afterPropertiesSet(); + + CountDownLatch countDownLatch = new CountDownLatch(10); + this.startThreads(taskExecutor, countDownLatch, 10); + + while (countDownLatch.getCount() > 0) { + Assert.assertEquals(10, taskExecutor.getPoolSize()); + } + } + + @Test + public void whenCorePoolSizeFiveAndMaxPoolSizeTenAndQueueCapacityTen_thenTenThreads() { + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.setCorePoolSize(5); + taskExecutor.setMaxPoolSize(10); + taskExecutor.setQueueCapacity(10); + taskExecutor.afterPropertiesSet(); + + CountDownLatch countDownLatch = new CountDownLatch(20); + this.startThreads(taskExecutor, countDownLatch, 20); + + while (countDownLatch.getCount() > 0) { + Assert.assertEquals(10, taskExecutor.getPoolSize()); + } + } +}