diff --git a/algorithms/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Point.java b/algorithms/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Point.java
new file mode 100644
index 0000000000..68b1e7c594
--- /dev/null
+++ b/algorithms/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Point.java
@@ -0,0 +1,29 @@
+package com.baeldung.algorithms.rectanglesoverlap;
+
+public class Point {
+
+ private int x;
+ private int y;
+
+ public Point(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public int getX() {
+ return x;
+ }
+
+ public void setX(int x) {
+ this.x = x;
+ }
+
+ public int getY() {
+ return y;
+ }
+
+ public void setY(int y) {
+ this.y = y;
+ }
+
+}
diff --git a/algorithms/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Rectangle.java b/algorithms/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Rectangle.java
new file mode 100644
index 0000000000..38f5edec61
--- /dev/null
+++ b/algorithms/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Rectangle.java
@@ -0,0 +1,40 @@
+package com.baeldung.algorithms.rectanglesoverlap;
+
+public class Rectangle {
+
+ private Point bottomLeft;
+ private Point topRight;
+
+ public Rectangle(Point bottomLeft, Point topRight) {
+ this.bottomLeft = bottomLeft;
+ this.topRight = topRight;
+ }
+
+ public Point getBottomLeft() {
+ return bottomLeft;
+ }
+
+ public void setBottomLeft(Point bottomLeft) {
+ this.bottomLeft = bottomLeft;
+ }
+
+ public Point getTopRight() {
+ return topRight;
+ }
+
+ public void setTopRight(Point topRight) {
+ this.topRight = topRight;
+ }
+
+ public boolean isOverlapping(Rectangle other) {
+ // one rectangle is to the top of the other
+ if (this.topRight.getY() < other.bottomLeft.getY() || this.bottomLeft.getY() > other.topRight.getY()) {
+ return false;
+ }
+ // one rectangle is to the left of the other
+ if (this.topRight.getX() < other.bottomLeft.getX() || this.bottomLeft.getX() > other.topRight.getX()) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/algorithms/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java b/algorithms/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java
new file mode 100644
index 0000000000..6707b34477
--- /dev/null
+++ b/algorithms/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java
@@ -0,0 +1,42 @@
+package com.baeldung.algorithms.rectanglesoverlap;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import org.junit.Test;
+
+import com.baeldung.algorithms.rectanglesoverlap.Point;
+import com.baeldung.algorithms.rectanglesoverlap.Rectangle;
+
+public class RectangleUnitTest {
+
+ @Test
+ public void givenTwoOverlappingRectangles_whenisOverlappingCalled_shouldReturnTrue() {
+ Rectangle rectangle1 = new Rectangle(new Point(2, 1), new Point(4, 3));
+ Rectangle rectangle2 = new Rectangle(new Point(1, 1), new Point(6, 4));
+ assertTrue(rectangle1.isOverlapping(rectangle2));
+
+ rectangle1 = new Rectangle(new Point(-5, -2), new Point(2, 3));
+ rectangle2 = new Rectangle(new Point(-2, -1), new Point(5, 2));
+ assertTrue(rectangle1.isOverlapping(rectangle2));
+
+ rectangle1 = new Rectangle(new Point(-5, 1), new Point(2, 4));
+ rectangle2 = new Rectangle(new Point(-2, -2), new Point(5, 5));
+ assertTrue(rectangle1.isOverlapping(rectangle2));
+ }
+
+ @Test
+ public void givenTwoNonOverlappingRectangles_whenisOverlappingCalled_shouldReturnFalse() {
+ Rectangle rectangle1 = new Rectangle(new Point(-5, 1), new Point(-3, 4));
+ Rectangle rectangle2 = new Rectangle(new Point(-2, -2), new Point(5, 5));
+ assertFalse(rectangle1.isOverlapping(rectangle2));
+
+ rectangle1 = new Rectangle(new Point(-5, 1), new Point(3, 4));
+ rectangle2 = new Rectangle(new Point(-2, -2), new Point(5, -1));
+ assertFalse(rectangle1.isOverlapping(rectangle2));
+
+ rectangle1 = new Rectangle(new Point(-2, 1), new Point(0, 3));
+ rectangle2 = new Rectangle(new Point(3, 1), new Point(5, 4));
+ assertFalse(rectangle1.isOverlapping(rectangle2));
+ }
+
+}
diff --git a/aws-lambda/pom.xml b/aws-lambda/pom.xml
index 3a2be70da6..c47c3cd86f 100644
--- a/aws-lambda/pom.xml
+++ b/aws-lambda/pom.xml
@@ -95,7 +95,6 @@
2.8.2
1.11.241
3.0.0
- 2.10
\ No newline at end of file
diff --git a/aws/pom.xml b/aws/pom.xml
index 26bc0c8037..ab63f6afa1 100644
--- a/aws/pom.xml
+++ b/aws/pom.xml
@@ -100,26 +100,6 @@
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
- ${maven-dependency-plugin.version}
-
-
- copy-dependencies
- test-compile
-
- copy-dependencies
-
-
- test
- so,dll,dylib
- ${project.basedir}/native-libs
-
-
-
-
@@ -144,7 +124,6 @@
1.10.L001
0.9.4.0006L
3.0.0
- 2.10
\ No newline at end of file
diff --git a/checker-plugin/pom.xml b/checker-plugin/pom.xml
index 7538340f69..45f0939e77 100644
--- a/checker-plugin/pom.xml
+++ b/checker-plugin/pom.xml
@@ -41,27 +41,6 @@
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
-
-
- properties
-
-
-
-
-
maven-compiler-plugin
${maven-compiler-plugin.version}
diff --git a/core-java-8/pom.xml b/core-java-8/pom.xml
index fa0d79e405..18bdaa15f4 100644
--- a/core-java-8/pom.xml
+++ b/core-java-8/pom.xml
@@ -116,23 +116,6 @@
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- prepare-package
-
- copy-dependencies
-
-
- ${project.build.directory}/libs
-
-
-
-
-
org.apache.maven.plugins
maven-compiler-plugin
diff --git a/core-java-9/logging.sh b/core-java-9/logging.sh
new file mode 100755
index 0000000000..c9b502f300
--- /dev/null
+++ b/core-java-9/logging.sh
@@ -0,0 +1,15 @@
+# compile logging module
+# javac --module-path mods -d mods/com.baeldung.logging src/modules/com.baeldung.logging/module-info.java src/modules/com.baeldung.logging/com/baeldung/logging/*.java
+
+# compile logging slf4j module
+javac --module-path mods -d mods/com.baeldung.logging.slf4j src/modules/com.baeldung.logging.slf4j/module-info.java src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/*.java
+
+
+# compile logging main app module
+javac --module-path mods -d mods/com.baeldung.logging.app src/modules/com.baeldung.logging.app/module-info.java src/modules/com.baeldung.logging.app/com/baeldung/logging/app/*.java
+
+# run logging main app
+# java --module-path mods -m com.baeldung.logging.app/com.baeldung.logging.app.MainApp
+
+# run looging main app using logback
+java --module-path mods -Dlogback.configurationFile=mods/logback.xml -m com.baeldung.logging.app/com.baeldung.logging.app.MainApp
diff --git a/core-java-9/mods/logback.xml b/core-java-9/mods/logback.xml
new file mode 100644
index 0000000000..c22c7a7130
--- /dev/null
+++ b/core-java-9/mods/logback.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} -- %msg%n
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-9/src/modules/com.baeldung.logging.app/com/baeldung/logging/app/MainApp.java b/core-java-9/src/modules/com.baeldung.logging.app/com/baeldung/logging/app/MainApp.java
new file mode 100644
index 0000000000..01f53d59e9
--- /dev/null
+++ b/core-java-9/src/modules/com.baeldung.logging.app/com/baeldung/logging/app/MainApp.java
@@ -0,0 +1,13 @@
+package com.baeldung.logging.app;
+
+import static java.lang.System.Logger.*;
+
+public class MainApp {
+
+ private static System.Logger LOGGER = System.getLogger("MainApp");
+
+ public static void main(String[] args) {
+ LOGGER.log(Level.ERROR, "error test");
+ LOGGER.log(Level.INFO, "info test");
+ }
+}
diff --git a/core-java-9/src/modules/com.baeldung.logging.app/module-info.java b/core-java-9/src/modules/com.baeldung.logging.app/module-info.java
new file mode 100644
index 0000000000..037c72b755
--- /dev/null
+++ b/core-java-9/src/modules/com.baeldung.logging.app/module-info.java
@@ -0,0 +1,2 @@
+module com.baeldung.logging.app {
+}
\ No newline at end of file
diff --git a/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java b/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java
new file mode 100644
index 0000000000..df41e071fd
--- /dev/null
+++ b/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLogger.java
@@ -0,0 +1,99 @@
+package com.baeldung.logging.slf4j;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ResourceBundle;
+
+public class Slf4jLogger implements System.Logger {
+
+ private final String name;
+ private final Logger logger;
+
+ public Slf4jLogger(String name) {
+ this.name = name;
+ logger = LoggerFactory.getLogger(name);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean isLoggable(Level level) {
+ switch (level) {
+ case OFF:
+ return false;
+ case TRACE:
+ return logger.isTraceEnabled();
+ case DEBUG:
+ return logger.isDebugEnabled();
+ case INFO:
+ return logger.isInfoEnabled();
+ case WARNING:
+ return logger.isWarnEnabled();
+ case ERROR:
+ return logger.isErrorEnabled();
+ case ALL:
+ default:
+ return true;
+ }
+ }
+
+ @Override
+ public void log(Level level, ResourceBundle bundle, String msg, Throwable thrown) {
+ if (!isLoggable(level)) {
+ return;
+ }
+
+ switch (level) {
+ case TRACE:
+ logger.trace(msg, thrown);
+ break;
+ case DEBUG:
+ logger.debug(msg, thrown);
+ break;
+ case INFO:
+ logger.info(msg, thrown);
+ break;
+ case WARNING:
+ logger.warn(msg, thrown);
+ break;
+ case ERROR:
+ logger.error(msg, thrown);
+ break;
+ case ALL:
+ default:
+ logger.info(msg, thrown);
+ }
+ }
+
+ @Override
+ public void log(Level level, ResourceBundle bundle, String format, Object... params) {
+ if (!isLoggable(level)) {
+ return;
+ }
+
+ switch (level) {
+ case TRACE:
+ logger.trace(format, params);
+ break;
+ case DEBUG:
+ logger.debug(format, params);
+ break;
+ case INFO:
+ logger.info(format, params);
+ break;
+ case WARNING:
+ logger.warn(format, params);
+ break;
+ case ERROR:
+ logger.error(format, params);
+ break;
+ case ALL:
+ default:
+ logger.info(format, params);
+ }
+ }
+}
diff --git a/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLoggerFinder.java b/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLoggerFinder.java
new file mode 100644
index 0000000000..97f7cccb92
--- /dev/null
+++ b/core-java-9/src/modules/com.baeldung.logging.slf4j/com/baeldung/logging/slf4j/Slf4jLoggerFinder.java
@@ -0,0 +1,8 @@
+package com.baeldung.logging.slf4j;
+
+public class Slf4jLoggerFinder extends System.LoggerFinder {
+ @Override
+ public System.Logger getLogger(String name, Module module) {
+ return new Slf4jLogger(name);
+ }
+}
diff --git a/core-java-9/src/modules/com.baeldung.logging.slf4j/module-info.java b/core-java-9/src/modules/com.baeldung.logging.slf4j/module-info.java
new file mode 100644
index 0000000000..311ca22f5b
--- /dev/null
+++ b/core-java-9/src/modules/com.baeldung.logging.slf4j/module-info.java
@@ -0,0 +1,6 @@
+module com.baeldung.logging.slf4j {
+ requires org.slf4j;
+ provides java.lang.System.LoggerFinder
+ with com.baeldung.logging.slf4j.Slf4jLoggerFinder;
+ exports com.baeldung.logging.slf4j;
+}
\ No newline at end of file
diff --git a/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/ConsoleLogger.java b/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/ConsoleLogger.java
new file mode 100644
index 0000000000..a495e6979d
--- /dev/null
+++ b/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/ConsoleLogger.java
@@ -0,0 +1,27 @@
+package com.baeldung.logging;
+
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+public class ConsoleLogger implements System.Logger {
+
+ @Override
+ public String getName() {
+ return "ConsoleLogger";
+ }
+
+ @Override
+ public boolean isLoggable(Level level) {
+ return true;
+ }
+
+ @Override
+ public void log(Level level, ResourceBundle bundle, String msg, Throwable thrown) {
+ System.out.printf("ConsoleLogger [%s]: %s - %s%n", level, msg, thrown);
+ }
+
+ @Override
+ public void log(Level level, ResourceBundle bundle, String format, Object... params) {
+ System.out.printf("ConsoleLogger [%s]: %s%n", level, MessageFormat.format(format, params));
+ }
+}
diff --git a/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/CustomLoggerFinder.java b/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/CustomLoggerFinder.java
new file mode 100644
index 0000000000..b38955f199
--- /dev/null
+++ b/core-java-9/src/modules/com.baeldung.logging/com/baeldung/logging/CustomLoggerFinder.java
@@ -0,0 +1,9 @@
+package com.baeldung.logging;
+
+public class CustomLoggerFinder extends System.LoggerFinder {
+
+ @Override
+ public System.Logger getLogger(String name, Module module) {
+ return new ConsoleLogger();
+ }
+}
diff --git a/core-java-9/src/modules/com.baeldung.logging/module-info.java b/core-java-9/src/modules/com.baeldung.logging/module-info.java
new file mode 100644
index 0000000000..4ca0af0225
--- /dev/null
+++ b/core-java-9/src/modules/com.baeldung.logging/module-info.java
@@ -0,0 +1,5 @@
+module com.baeldung.logging {
+ provides java.lang.System.LoggerFinder
+ with com.baeldung.logging.CustomLoggerFinder;
+ exports com.baeldung.logging;
+}
\ No newline at end of file
diff --git a/core-java-collections/src/main/java/com/baeldung/java/map/MapUtil.java b/core-java-collections/src/main/java/com/baeldung/java/map/MapUtil.java
new file mode 100644
index 0000000000..688c7592f3
--- /dev/null
+++ b/core-java-collections/src/main/java/com/baeldung/java/map/MapUtil.java
@@ -0,0 +1,44 @@
+/**
+ *
+ */
+package com.baeldung.java.map;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.stream.Stream;
+
+/**
+ * @author swpraman
+ *
+ */
+public class MapUtil {
+
+ public static Stream keys(Map map, V value) {
+ return map.entrySet()
+ .stream()
+ .filter(entry -> value.equals(entry.getValue()))
+ .map(Map.Entry::getKey);
+ }
+
+ public static Set getKeys(Map map, V value) {
+ Set keys = new HashSet<>();
+ for (Entry entry : map.entrySet()) {
+ if (entry.getValue().equals(value)) {
+ keys.add(entry.getKey());
+ }
+ }
+ return keys;
+ }
+
+ public static K getKey(Map map, V value) {
+ for (Entry entry : map.entrySet()) {
+ if (entry.getValue().equals(value)) {
+ return entry.getKey();
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/core-java-collections/src/test/java/com/baeldung/collection/ClearVsRemoveAllUnitTest.java b/core-java-collections/src/test/java/com/baeldung/collection/ClearVsRemoveAllUnitTest.java
new file mode 100644
index 0000000000..8b0a7ef0db
--- /dev/null
+++ b/core-java-collections/src/test/java/com/baeldung/collection/ClearVsRemoveAllUnitTest.java
@@ -0,0 +1,40 @@
+package com.baeldung.collection;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Unit tests demonstrating differences between ArrayList#clear() and ArrayList#removeAll()
+ */
+class ClearVsRemoveAllUnitTest {
+
+ /*
+ * Tests
+ */
+ @Test
+ void givenArrayListWithElements_whenClear_thenListBecomesEmpty() {
+ Collection collection = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
+
+ collection.clear();
+
+ assertTrue(collection.isEmpty());
+ }
+
+ @Test
+ void givenTwoArrayListsWithCommonElements_whenRemoveAll_thenFirstListMissElementsFromSecondList() {
+ Collection firstCollection = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
+ Collection secondCollection = new ArrayList<>(Arrays.asList(3, 4, 5, 6, 7));
+
+ firstCollection.removeAll(secondCollection);
+
+ assertEquals(Arrays.asList(1, 2), firstCollection);
+ assertEquals(Arrays.asList(3, 4, 5, 6, 7), secondCollection);
+ }
+
+}
diff --git a/core-java-collections/src/test/java/com/baeldung/java/map/MapUtilUnitTest.java b/core-java-collections/src/test/java/com/baeldung/java/map/MapUtilUnitTest.java
new file mode 100644
index 0000000000..e31385e972
--- /dev/null
+++ b/core-java-collections/src/test/java/com/baeldung/java/map/MapUtilUnitTest.java
@@ -0,0 +1,104 @@
+/**
+ *
+ */
+package com.baeldung.java.map;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.apache.commons.collections4.BidiMap;
+import org.apache.commons.collections4.bidimap.DualHashBidiMap;
+import org.junit.Test;
+
+import com.google.common.collect.HashBiMap;
+
+/**
+ * @author swpraman
+ *
+ */
+public class MapUtilUnitTest {
+
+
+ @Test
+ public void whenUsingImperativeWayForSingleKey_shouldReturnSingleKey() {
+ Map capitalCountryMap = new HashMap<>();
+ capitalCountryMap.put("Tokyo", "Japan");
+ capitalCountryMap.put("New Delhi", "India");
+ assertEquals("New Delhi", MapUtil.getKey(capitalCountryMap, "India"));
+ }
+
+ @Test
+ public void whenUsingImperativeWayForAllKeys_shouldReturnAllKeys() {
+ Map capitalCountryMap = new HashMap<>();
+ capitalCountryMap.put("Tokyo", "Japan");
+ capitalCountryMap.put("Berlin", "Germany");
+ capitalCountryMap.put("Cape Town", "South Africa");
+ capitalCountryMap.put("Pretoria", "South Africa");
+ capitalCountryMap.put("Bloemfontein", "South Africa");
+
+ assertEquals(new HashSet(Arrays.asList(
+ new String[] {"Cape Town", "Pretoria", "Bloemfontein"})),
+ MapUtil.getKeys(capitalCountryMap, "South Africa"));
+ }
+
+ @Test
+ public void whenUsingFunctionalWayForSingleKey_shouldReturnSingleKey() {
+ Map capitalCountryMap = new HashMap<>();
+ capitalCountryMap.put("Tokyo", "Japan");
+ capitalCountryMap.put("Berlin", "Germany");
+ assertEquals("Berlin", MapUtil.keys(capitalCountryMap, "Germany").findFirst().get());
+ }
+
+ @Test
+ public void whenUsingFunctionalWayForAllKeys_shouldReturnAllKeys() {
+ Map capitalCountryMap = new HashMap<>();
+ capitalCountryMap.put("Tokyo", "Japan");
+ capitalCountryMap.put("Berlin", "Germany");
+ capitalCountryMap.put("Cape Town", "South Africa");
+ capitalCountryMap.put("Pretoria", "South Africa");
+ capitalCountryMap.put("Bloemfontein", "South Africa");
+ assertEquals(new HashSet(Arrays.asList(
+ new String[] {"Cape Town", "Pretoria", "Bloemfontein"})),
+ MapUtil.keys(capitalCountryMap, "South Africa").collect(Collectors.toSet()));
+ }
+
+ @Test
+ public void whenUsingBidiMap_shouldReturnKey() {
+ BidiMap capitalCountryMap = new DualHashBidiMap();
+ capitalCountryMap.put("Berlin", "Germany");
+ capitalCountryMap.put("Cape Town", "South Africa");
+ assertEquals("Berlin", capitalCountryMap.getKey("Germany"));
+ }
+
+ @Test
+ public void whenUsingBidiMapAddDuplicateValue_shouldRemoveOldEntry() {
+ BidiMap capitalCountryMap = new DualHashBidiMap();
+ capitalCountryMap.put("Berlin", "Germany");
+ capitalCountryMap.put("Cape Town", "South Africa");
+ capitalCountryMap.put("Pretoria", "South Africa");
+ assertEquals("Pretoria", capitalCountryMap.getKey("South Africa"));
+ }
+
+ @Test
+ public void whenUsingBiMap_shouldReturnKey() {
+ HashBiMap capitalCountryMap = HashBiMap.create();
+ capitalCountryMap.put("Berlin", "Germany");
+ capitalCountryMap.put("Cape Town", "South Africa");
+ assertEquals("Berlin", capitalCountryMap.inverse().get("Germany"));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void whenUsingBiMapAddDuplicateValue_shouldThrowException() {
+ HashBiMap capitalCountryMap = HashBiMap.create();
+ capitalCountryMap.put("Berlin", "Germany");
+ capitalCountryMap.put("Cape Town", "South Africa");
+ capitalCountryMap.put("Pretoria", "South Africa");
+ assertEquals("Berlin", capitalCountryMap.inverse().get("Germany"));
+ }
+
+}
diff --git a/core-java-concurrency-collections/pom.xml b/core-java-concurrency-collections/pom.xml
index 5e0a80d33c..9473de8c51 100644
--- a/core-java-concurrency-collections/pom.xml
+++ b/core-java-concurrency-collections/pom.xml
@@ -57,26 +57,6 @@
true
-
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- prepare-package
-
- copy-dependencies
-
-
- ${project.build.directory}/libs
-
-
-
-
-
-
diff --git a/core-java-concurrency/pom.xml b/core-java-concurrency/pom.xml
index eb81983a2a..bd22253c2c 100644
--- a/core-java-concurrency/pom.xml
+++ b/core-java-concurrency/pom.xml
@@ -57,26 +57,6 @@
true
-
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- prepare-package
-
- copy-dependencies
-
-
- ${project.build.directory}/libs
-
-
-
-
-
-
diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/yield/ThreadYield.java b/core-java-concurrency/src/main/java/com/baeldung/concurrent/yield/ThreadYield.java
new file mode 100644
index 0000000000..b31a04015f
--- /dev/null
+++ b/core-java-concurrency/src/main/java/com/baeldung/concurrent/yield/ThreadYield.java
@@ -0,0 +1,17 @@
+package com.baeldung.concurrent.yield;
+
+public class ThreadYield {
+ public static void main(String[] args) {
+ Runnable r = () -> {
+ int counter = 0;
+ while (counter < 2) {
+ System.out.println(Thread.currentThread()
+ .getName());
+ counter++;
+ Thread.yield();
+ }
+ };
+ new Thread(r).start();
+ new Thread(r).start();
+ }
+}
diff --git a/core-java-sun/pom.xml b/core-java-sun/pom.xml
index 7292335232..57d5e9da5b 100644
--- a/core-java-sun/pom.xml
+++ b/core-java-sun/pom.xml
@@ -166,22 +166,6 @@
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- prepare-package
-
- copy-dependencies
-
-
- ${project.build.directory}/libs
-
-
-
-
org.apache.maven.plugins
maven-jar-plugin
diff --git a/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java b/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java
new file mode 100644
index 0000000000..8dbfcaf5e7
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsManualTest.java
@@ -0,0 +1,100 @@
+package com.baeldung.removingdecimals;
+
+import org.junit.Test;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This benchmark compares some of the approaches to formatting a floating-point
+ * value into a {@link String} while removing the decimal part.
+ *
+ * To run, simply run the {@link RemovingDecimalsManualTest#runBenchmarks()} test
+ * at the end of this class.
+ *
+ * The benchmark takes about 15 minutes to run. Since it is using {@link Mode#Throughput},
+ * higher numbers mean better performance.
+ */
+@BenchmarkMode(Mode.Throughput)
+@Warmup(iterations = 5)
+@Measurement(iterations = 20)
+@OutputTimeUnit(TimeUnit.MICROSECONDS)
+@State(Scope.Benchmark)
+public class RemovingDecimalsManualTest {
+ @Param(value = {"345.56", "345345345.56", "345345345345345345.56"}) double doubleValue;
+
+ NumberFormat nf;
+ DecimalFormat df;
+
+ @Setup
+ public void readyFormatters() {
+ nf = NumberFormat.getInstance();
+ nf.setMaximumFractionDigits(0);
+ df = new DecimalFormat("#,###");
+ }
+
+ @Benchmark
+ public String whenCastToInt_thenValueIsTruncated() {
+ return String.valueOf((int) doubleValue);
+ }
+
+ @Benchmark
+ public String whenUsingStringFormat_thenValueIsRounded() {
+ return String.format("%.0f", doubleValue);
+ }
+
+ @Benchmark
+ public String whenUsingNumberFormat_thenValueIsRounded() {
+ nf.setRoundingMode(RoundingMode.HALF_UP);
+ return nf.format(doubleValue);
+ }
+
+ @Benchmark
+ public String whenUsingNumberFormatWithFloor_thenValueIsTruncated() {
+ nf.setRoundingMode(RoundingMode.FLOOR);
+ return nf.format(doubleValue);
+ }
+
+ @Benchmark
+ public String whenUsingDecimalFormat_thenValueIsRounded() {
+ df.setRoundingMode(RoundingMode.HALF_UP);
+ return df.format(doubleValue);
+ }
+
+ @Benchmark
+ public String whenUsingDecimalFormatWithFloor_thenValueIsTruncated() {
+ df.setRoundingMode(RoundingMode.FLOOR);
+ return df.format(doubleValue);
+ }
+
+ @Benchmark
+ public String whenUsingBigDecimalDoubleValue_thenValueIsTruncated() {
+ BigDecimal big = new BigDecimal(doubleValue);
+ big = big.setScale(0, RoundingMode.FLOOR);
+ return big.toString();
+ }
+
+ @Benchmark
+ public String whenUsingBigDecimalDoubleValueWithHalfUp_thenValueIsRounded() {
+ BigDecimal big = new BigDecimal(doubleValue);
+ big = big.setScale(0, RoundingMode.HALF_UP);
+ return big.toString();
+ }
+
+ @Test
+ public void runBenchmarks() throws Exception {
+ Options options = new OptionsBuilder()
+ .include(this.getClass().getSimpleName()).threads(1)
+ .forks(1).shouldFailOnError(true).shouldDoGC(true)
+ .jvmArgs("-server").build();
+
+ new Runner(options).run();
+ }
+}
diff --git a/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java b/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java
new file mode 100644
index 0000000000..2f634b553b
--- /dev/null
+++ b/core-java/src/test/java/com/baeldung/removingdecimals/RemovingDecimalsUnitTest.java
@@ -0,0 +1,95 @@
+package com.baeldung.removingdecimals;
+
+import org.junit.Test;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+/**
+ * Tests that demonstrate some different approaches for formatting a
+ * floating-point value into a {@link String} while removing the decimal part.
+ */
+public class RemovingDecimalsUnitTest {
+ private final double doubleValue = 345.56;
+
+ @Test
+ public void whenCastToInt_thenValueIsTruncated() {
+ String truncated = String.valueOf((int) doubleValue);
+ assertEquals("345", truncated);
+ }
+
+ @Test
+ public void givenALargeDouble_whenCastToInt_thenValueIsNotTruncated() {
+ double outOfIntRange = 6_000_000_000.56;
+ String truncationAttempt = String.valueOf((int) outOfIntRange);
+ assertNotEquals("6000000000", truncationAttempt);
+ }
+
+ @Test
+ public void whenUsingStringFormat_thenValueIsRounded() {
+ String rounded = String.format("%.0f", doubleValue);
+ assertEquals("346", rounded);
+ }
+
+ @Test
+ public void givenALargeDouble_whenUsingStringFormat_thenValueIsStillRounded() {
+ double outOfIntRange = 6_000_000_000.56;
+ String rounded = String.format("%.0f", outOfIntRange);
+ assertEquals("6000000001", rounded);
+ }
+
+ @Test
+ public void whenUsingNumberFormat_thenValueIsRounded() {
+ NumberFormat nf = NumberFormat.getInstance();
+ nf.setMaximumFractionDigits(0);
+ nf.setRoundingMode(RoundingMode.HALF_UP);
+ String rounded = nf.format(doubleValue);
+ assertEquals("346", rounded);
+ }
+
+ @Test
+ public void whenUsingNumberFormatWithFloor_thenValueIsTruncated() {
+ NumberFormat nf = NumberFormat.getInstance();
+ nf.setMaximumFractionDigits(0);
+ nf.setRoundingMode(RoundingMode.FLOOR);
+ String truncated = nf.format(doubleValue);
+ assertEquals("345", truncated);
+ }
+
+ @Test
+ public void whenUsingDecimalFormat_thenValueIsRounded() {
+ DecimalFormat df = new DecimalFormat("#,###");
+ df.setRoundingMode(RoundingMode.HALF_UP);
+ String rounded = df.format(doubleValue);
+ assertEquals("346", rounded);
+ }
+
+ @Test
+ public void whenUsingDecimalFormatWithFloor_thenValueIsTruncated() {
+ DecimalFormat df = new DecimalFormat("#,###");
+ df.setRoundingMode(RoundingMode.FLOOR);
+ String truncated = df.format(doubleValue);
+ assertEquals("345", truncated);
+ }
+
+ @Test
+ public void whenUsingBigDecimalDoubleValue_thenValueIsTruncated() {
+ BigDecimal big = new BigDecimal(doubleValue);
+ big = big.setScale(0, RoundingMode.FLOOR);
+ String truncated = big.toString();
+ assertEquals("345", truncated);
+ }
+
+ @Test
+ public void whenUsingBigDecimalDoubleValueWithHalfUp_thenValueIsRounded() {
+ BigDecimal big = new BigDecimal(doubleValue);
+ big = big.setScale(0, RoundingMode.HALF_UP);
+ String truncated = big.toString();
+ assertEquals("346", truncated);
+ }
+}
diff --git a/core-kotlin/README.md b/core-kotlin/README.md
index dc8b299165..f63451bc02 100644
--- a/core-kotlin/README.md
+++ b/core-kotlin/README.md
@@ -8,7 +8,6 @@
- [Generics in Kotlin](http://www.baeldung.com/kotlin-generics)
- [Introduction to Kotlin Coroutines](http://www.baeldung.com/kotlin-coroutines)
- [Destructuring Declarations in Kotlin](http://www.baeldung.com/kotlin-destructuring-declarations)
-- [Kotlin with Mockito](http://www.baeldung.com/kotlin-mockito)
- [Lazy Initialization in Kotlin](http://www.baeldung.com/kotlin-lazy-initialization)
- [Overview of Kotlin Collections API](http://www.baeldung.com/kotlin-collections-api)
- [Converting a List to Map in Kotlin](http://www.baeldung.com/kotlin-list-to-map)
@@ -19,8 +18,6 @@
- [Extension Methods in Kotlin](http://www.baeldung.com/kotlin-extension-methods)
- [Infix Functions in Kotlin](http://www.baeldung.com/kotlin-infix-functions)
- [Try-with-resources in Kotlin](http://www.baeldung.com/kotlin-try-with-resources)
-- [HTTP Requests with Kotlin and khttp](http://www.baeldung.com/kotlin-khttp)
-- [Kotlin Dependency Injection with Kodein](http://www.baeldung.com/kotlin-kodein-dependency-injection)
- [Regular Expressions in Kotlin](http://www.baeldung.com/kotlin-regular-expressions)
- [Objects in Kotlin](http://www.baeldung.com/kotlin-objects)
- [Reading from a File in Kotlin](http://www.baeldung.com/kotlin-read-file)
@@ -28,11 +25,7 @@
- [Filtering Kotlin Collections](http://www.baeldung.com/kotlin-filter-collection)
- [Writing to a File in Kotlin](http://www.baeldung.com/kotlin-write-file)
- [Lambda Expressions in Kotlin](http://www.baeldung.com/kotlin-lambda-expressions)
-- [Writing Specifications with Kotlin and Spek](http://www.baeldung.com/kotlin-spek)
-- [Processing JSON with Kotlin and Klaxson](http://www.baeldung.com/kotlin-json-klaxson)
- [Kotlin String Templates](http://www.baeldung.com/kotlin-string-template)
-- [Java EE 8 Security API](http://www.baeldung.com/java-ee-8-security)
-- [Kotlin with Ktor](http://www.baeldung.com/kotlin-ktor)
- [Working with Enums in Kotlin](http://www.baeldung.com/kotlin-enum)
- [Create a Java and Kotlin Project with Maven](http://www.baeldung.com/kotlin-maven-java-project)
- [Reflection with Kotlin](http://www.baeldung.com/kotlin-reflection)
@@ -40,5 +33,4 @@
- [Idiomatic Logging in Kotlin](http://www.baeldung.com/kotlin-logging)
- [Kotlin Constructors](https://www.baeldung.com/kotlin-constructors)
- [Creational Design Patterns in Kotlin: Builder](https://www.baeldung.com/kotlin-builder-pattern)
-- [Kotlin Nested and Inner Classes](https://www.baeldung.com/kotlin-inner-classes)
-- [Guide to the Kotlin Exposed Framework](https://www.baeldung.com/kotlin-exposed-persistence)
+- [Kotlin Nested and Inner Classes](https://www.baeldung.com/kotlin-inner-classes)
\ No newline at end of file
diff --git a/core-kotlin/build.gradle b/core-kotlin/build.gradle
index 6c1e06aa25..2b6527fca7 100755
--- a/core-kotlin/build.gradle
+++ b/core-kotlin/build.gradle
@@ -6,7 +6,6 @@ version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.2.41'
- ext.ktor_version = '0.9.2'
repositories {
mavenCentral()
@@ -44,14 +43,6 @@ sourceSets {
}
dependencies {
- compile "io.ktor:ktor-server-netty:$ktor_version"
compile "ch.qos.logback:logback-classic:1.2.1"
- compile "io.ktor:ktor-gson:$ktor_version"
testCompile group: 'junit', name: 'junit', version: '4.12'
- implementation 'com.beust:klaxon:3.0.1'
-
-}
-task runServer(type: JavaExec) {
- main = 'APIServer'
- classpath = sourceSets.main.runtimeClasspath
}
\ No newline at end of file
diff --git a/core-kotlin/kotlin-ktor/webapp/WEB-INF/web.xml b/core-kotlin/kotlin-ktor/webapp/WEB-INF/web.xml
deleted file mode 100755
index 513a80cb27..0000000000
--- a/core-kotlin/kotlin-ktor/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-
- io.ktor.ktor.config
- application.conf
-
-
-
- KtorServlet
- KtorServlet
- io.ktor.server.servlet.ServletApplicationEngine
-
-
- true
-
-
-
- 304857600
- 304857600
- 0
-
-
-
-
- KtorServlet
- /
-
-
-
\ No newline at end of file
diff --git a/core-kotlin/pom.xml b/core-kotlin/pom.xml
index 88f54963ed..0894a57320 100644
--- a/core-kotlin/pom.xml
+++ b/core-kotlin/pom.xml
@@ -12,33 +12,7 @@
../parent-kotlin
-
-
- exposed
- exposed
- https://dl.bintray.com/kotlin/exposed
-
-
-
-
- org.jetbrains.spek
- spek-api
- 1.1.5
- test
-
-
- org.jetbrains.spek
- spek-subject-extension
- 1.1.5
- test
-
-
- org.jetbrains.spek
- spek-junit-platform-engine
- 1.1.5
- test
-
org.apache.commons
commons-math3
@@ -50,38 +24,12 @@
${junit.platform.version}
test
-
- khttp
- khttp
- ${khttp.version}
-
-
- com.nhaarman
- mockito-kotlin
- ${mockito-kotlin.version}
- test
-
-
- com.github.salomonbrys.kodein
- kodein
- ${kodein.version}
-
org.assertj
assertj-core
${assertj.version}
test
-
- com.beust
- klaxon
- ${klaxon.version}
-
-
- org.jetbrains.exposed
- exposed
- ${exposed.version}
-
com.h2database
h2
@@ -107,19 +55,20 @@
fuel-coroutines
${fuel.version}
+
+ nl.komponents.kovenant
+ kovenant
+ 3.3.0
+ pom
+
- 1.5.0
- 4.1.0
- 3.0.4
- 0.1.0
3.6.1
1.1.1
5.2.0
3.10.0
1.4.197
- 0.10.4
1.15.0
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/ktor/APIServer.kt b/core-kotlin/src/main/kotlin/com/baeldung/ktor/APIServer.kt
deleted file mode 100755
index a12182ccc8..0000000000
--- a/core-kotlin/src/main/kotlin/com/baeldung/ktor/APIServer.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-@file:JvmName("APIServer")
-
-
-import io.ktor.application.call
-import io.ktor.application.install
-import io.ktor.features.CallLogging
-import io.ktor.features.ContentNegotiation
-import io.ktor.features.DefaultHeaders
-import io.ktor.gson.gson
-import io.ktor.request.path
-import io.ktor.request.receive
-import io.ktor.response.respond
-import io.ktor.routing.*
-import io.ktor.server.engine.embeddedServer
-import io.ktor.server.netty.Netty
-import org.slf4j.event.Level
-
-data class Author(val name: String, val website: String)
-data class ToDo(var id: Int, val name: String, val description: String, val completed: Boolean)
-
-fun main(args: Array) {
-
- val toDoList = ArrayList();
- val jsonResponse = """{
- "id": 1,
- "task": "Pay waterbill",
- "description": "Pay water bill today",
- }"""
-
-
- embeddedServer(Netty, 8080) {
- install(DefaultHeaders) {
- header("X-Developer", "Baeldung")
- }
- install(CallLogging) {
- level = Level.DEBUG
- filter { call -> call.request.path().startsWith("/todo") }
- filter { call -> call.request.path().startsWith("/author") }
- }
- install(ContentNegotiation) {
- gson {
- setPrettyPrinting()
- }
- }
- routing() {
- route("/todo") {
- post {
- var toDo = call.receive();
- toDo.id = toDoList.size;
- toDoList.add(toDo);
- call.respond("Added")
-
- }
- delete("/{id}") {
- call.respond(toDoList.removeAt(call.parameters["id"]!!.toInt()));
- }
- get("/{id}") {
-
- call.respond(toDoList[call.parameters["id"]!!.toInt()]);
- }
- get {
- call.respond(toDoList);
- }
- }
- get("/author"){
- call.respond(Author("Baeldung","baeldung.com"));
-
- }
-
-
- }
- }.start(wait = true)
-}
\ No newline at end of file
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTest.kt
new file mode 100644
index 0000000000..469118f0f6
--- /dev/null
+++ b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTest.kt
@@ -0,0 +1,191 @@
+package com.baeldung.kotlin
+
+import nl.komponents.kovenant.*
+import nl.komponents.kovenant.Kovenant.deferred
+import nl.komponents.kovenant.combine.and
+import nl.komponents.kovenant.combine.combine
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+import java.io.IOException
+import java.util.*
+import java.util.concurrent.TimeUnit
+
+class KovenantTest {
+ @Before
+ fun setupTestMode() {
+ Kovenant.testMode { error ->
+ println("An unexpected error occurred")
+ Assert.fail(error.message)
+ }
+ }
+
+ @Test
+ fun testSuccessfulDeferred() {
+ val def = deferred()
+ Assert.assertFalse(def.promise.isDone())
+
+ def.resolve(1L)
+ Assert.assertTrue(def.promise.isDone())
+ Assert.assertTrue(def.promise.isSuccess())
+ Assert.assertFalse(def.promise.isFailure())
+ }
+
+ @Test
+ fun testFailedDeferred() {
+ val def = deferred()
+ Assert.assertFalse(def.promise.isDone())
+
+ def.reject(RuntimeException())
+ Assert.assertTrue(def.promise.isDone())
+ Assert.assertFalse(def.promise.isSuccess())
+ Assert.assertTrue(def.promise.isFailure())
+ }
+
+ @Test
+ fun testResolveDeferredTwice() {
+ val def = deferred()
+ def.resolve(1L)
+ try {
+ def.resolve(1L)
+ } catch (e: AssertionError) {
+ // Expected.
+ // This is slightly unusual. The AssertionError comes from Assert.fail() from setupTestMode()
+ }
+ }
+
+ @Test
+ fun testSuccessfulTask() {
+ val promise = task { 1L }
+ Assert.assertTrue(promise.isDone())
+ Assert.assertTrue(promise.isSuccess())
+ Assert.assertFalse(promise.isFailure())
+ }
+
+ @Test
+ fun testFailedTask() {
+ val promise = task { throw RuntimeException() }
+ Assert.assertTrue(promise.isDone())
+ Assert.assertFalse(promise.isSuccess())
+ Assert.assertTrue(promise.isFailure())
+ }
+
+ @Test
+ fun testCallbacks() {
+ val promise = task { 1L }
+
+ promise.success {
+ println("This was a success")
+ Assert.assertEquals(1L, it)
+ }
+
+ promise.fail {
+ println(it)
+ Assert.fail("This shouldn't happen")
+ }
+
+ promise.always {
+ println("This always happens")
+ }
+ }
+
+ @Test
+ fun testGetValues() {
+ val promise = task { 1L }
+ Assert.assertEquals(1L, promise.get())
+ }
+
+ @Test
+ fun testAllSucceed() {
+ val numbers = all(
+ task { 1L },
+ task { 2L },
+ task { 3L }
+ )
+
+ Assert.assertEquals(listOf(1L, 2L, 3L), numbers.get())
+ }
+
+ @Test
+ fun testOneFails() {
+ val runtimeException = RuntimeException()
+
+ val numbers = all(
+ task { 1L },
+ task { 2L },
+ task { throw runtimeException }
+ )
+
+ Assert.assertEquals(runtimeException, numbers.getError())
+ }
+
+ @Test
+ fun testAnySucceeds() {
+ val promise = any(
+ task {
+ TimeUnit.SECONDS.sleep(3)
+ 1L
+ },
+ task {
+ TimeUnit.SECONDS.sleep(2)
+ 2L
+ },
+ task {
+ TimeUnit.SECONDS.sleep(1)
+ 3L
+ }
+ )
+
+ Assert.assertTrue(promise.isDone())
+ Assert.assertTrue(promise.isSuccess())
+ Assert.assertFalse(promise.isFailure())
+ }
+
+ @Test
+ fun testAllFails() {
+ val runtimeException = RuntimeException()
+ val ioException = IOException()
+ val illegalStateException = IllegalStateException()
+ val promise = any(
+ task {
+ TimeUnit.SECONDS.sleep(3)
+ throw runtimeException
+ },
+ task {
+ TimeUnit.SECONDS.sleep(2)
+ throw ioException
+ },
+ task {
+ TimeUnit.SECONDS.sleep(1)
+ throw illegalStateException
+ }
+ )
+
+ Assert.assertTrue(promise.isDone())
+ Assert.assertFalse(promise.isSuccess())
+ Assert.assertTrue(promise.isFailure())
+ }
+
+ @Test
+ fun testSimpleCombine() {
+ val promise = task { 1L } and task { "Hello" }
+ val result = promise.get()
+
+ Assert.assertEquals(1L, result.first)
+ Assert.assertEquals("Hello", result.second)
+ }
+
+ @Test
+ fun testLongerCombine() {
+ val promise = combine(
+ task { 1L },
+ task { "Hello" },
+ task { Currency.getInstance("USD") }
+ )
+ val result = promise.get()
+
+ Assert.assertEquals(1L, result.first)
+ Assert.assertEquals("Hello", result.second)
+ Assert.assertEquals(Currency.getInstance("USD"), result.third)
+ }
+}
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTimeoutTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTimeoutTest.kt
new file mode 100644
index 0000000000..e37d2cc2fa
--- /dev/null
+++ b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/KovenantTimeoutTest.kt
@@ -0,0 +1,38 @@
+package com.baeldung.kotlin
+
+import nl.komponents.kovenant.Promise
+import nl.komponents.kovenant.any
+import nl.komponents.kovenant.task
+import org.junit.Assert
+import org.junit.Ignore
+import org.junit.Test
+
+@Ignore
+// Note that this can not run in the same test run if KovenantTest has already been executed
+class KovenantTimeoutTest {
+ @Test
+ fun testTimeout() {
+ val promise = timedTask(1000) { "Hello" }
+ val result = promise.get()
+ Assert.assertEquals("Hello", result)
+ }
+
+ @Test
+ fun testTimeoutExpired() {
+ val promise = timedTask(1000) {
+ Thread.sleep(3000)
+ "Hello"
+ }
+ val result = promise.get()
+ Assert.assertNull(result)
+ }
+
+ fun timedTask(millis: Long, body: () -> T) : Promise> {
+ val timeoutTask = task {
+ Thread.sleep(millis)
+ null
+ }
+ val activeTask = task(body = body)
+ return any(activeTask, timeoutTask)
+ }
+}
diff --git a/disruptor/pom.xml b/disruptor/pom.xml
index d3cef3bd9b..c26dcc0cd4 100644
--- a/disruptor/pom.xml
+++ b/disruptor/pom.xml
@@ -36,22 +36,6 @@
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- prepare-package
-
- copy-dependencies
-
-
- ${project.build.directory}/libs
-
-
-
-
org.apache.maven.plugins
maven-jar-plugin
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/proxy/BatchEmployee.java b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/BatchEmployee.java
new file mode 100644
index 0000000000..00643ab3dd
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/BatchEmployee.java
@@ -0,0 +1,56 @@
+package com.baeldung.hibernate.proxy;
+
+import org.hibernate.annotations.BatchSize;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+@Entity
+@BatchSize(size = 5)
+public class BatchEmployee implements Serializable {
+
+ @Id
+ @GeneratedValue (strategy = GenerationType.SEQUENCE)
+ private Long id;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ private Boss boss;
+
+ @Column(name = "name")
+ private String name;
+
+ @Column(name = "surname")
+ private String surname;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Boss getBoss() {
+ return boss;
+ }
+
+ public void setBoss(Boss boss) {
+ this.boss = boss;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getSurname() {
+ return surname;
+ }
+
+ public void setSurname(String surname) {
+ this.surname = surname;
+ }
+}
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Boss.java b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Boss.java
new file mode 100644
index 0000000000..b6e01814d0
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Boss.java
@@ -0,0 +1,49 @@
+package com.baeldung.hibernate.proxy;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+@Entity
+public class Boss implements Serializable {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.SEQUENCE)
+ private Long id;
+
+ @Column(name = "name")
+ private String name;
+
+ @Column(name = "surname")
+ private String surname;
+
+ public Boss() { }
+
+ public Boss(String name, String surname) {
+ this.name = name;
+ this.surname = surname;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getSurname() {
+ return surname;
+ }
+
+ public void setSurname(String surname) {
+ this.surname = surname;
+ }
+}
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Employee.java b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Employee.java
new file mode 100644
index 0000000000..6bc64c35ef
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/Employee.java
@@ -0,0 +1,53 @@
+package com.baeldung.hibernate.proxy;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+@Entity
+public class Employee implements Serializable {
+
+ @Id
+ @GeneratedValue (strategy = GenerationType.SEQUENCE)
+ private Long id;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ private Boss boss;
+
+ @Column(name = "name")
+ private String name;
+
+ @Column(name = "surname")
+ private String surname;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Boss getBoss() {
+ return boss;
+ }
+
+ public void setBoss(Boss boss) {
+ this.boss = boss;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getSurname() {
+ return surname;
+ }
+
+ public void setSurname(String surname) {
+ this.surname = surname;
+ }
+}
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/proxy/HibernateUtil.java b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/HibernateUtil.java
new file mode 100644
index 0000000000..e6ad0432bd
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/proxy/HibernateUtil.java
@@ -0,0 +1,57 @@
+package com.baeldung.hibernate.proxy;
+
+import org.apache.commons.lang3.StringUtils;
+import org.hibernate.SessionFactory;
+import org.hibernate.boot.Metadata;
+import org.hibernate.boot.MetadataSources;
+import org.hibernate.boot.SessionFactoryBuilder;
+import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+import org.hibernate.service.ServiceRegistry;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Properties;
+
+public class HibernateUtil {
+
+ private static SessionFactory sessionFactory;
+ private static String PROPERTY_FILE_NAME;
+
+ public static SessionFactory getSessionFactory(String propertyFileName) throws IOException {
+ PROPERTY_FILE_NAME = propertyFileName;
+ if (sessionFactory == null) {
+ ServiceRegistry serviceRegistry = configureServiceRegistry();
+ sessionFactory = getSessionFactoryBuilder(serviceRegistry).build();
+ }
+ return sessionFactory;
+ }
+
+ private static SessionFactoryBuilder getSessionFactoryBuilder(ServiceRegistry serviceRegistry) {
+ MetadataSources metadataSources = new MetadataSources(serviceRegistry);
+ metadataSources.addPackage("com.baeldung.hibernate.proxy");
+ metadataSources.addAnnotatedClass(Boss.class);
+ metadataSources.addAnnotatedClass(Employee.class);
+
+ Metadata metadata = metadataSources.buildMetadata();
+ return metadata.getSessionFactoryBuilder();
+
+ }
+
+ private static ServiceRegistry configureServiceRegistry() throws IOException {
+ Properties properties = getProperties();
+ return new StandardServiceRegistryBuilder().applySettings(properties)
+ .build();
+ }
+
+ private static Properties getProperties() throws IOException {
+ Properties properties = new Properties();
+ URL propertiesURL = Thread.currentThread()
+ .getContextClassLoader()
+ .getResource(StringUtils.defaultString(PROPERTY_FILE_NAME, "hibernate.properties"));
+ try (FileInputStream inputStream = new FileInputStream(propertiesURL.getFile())) {
+ properties.load(inputStream);
+ }
+ return properties;
+ }
+}
diff --git a/hibernate5/src/test/java/com/baeldung/hibernate/proxy/HibernateProxyUnitTest.java b/hibernate5/src/test/java/com/baeldung/hibernate/proxy/HibernateProxyUnitTest.java
new file mode 100644
index 0000000000..fa41797dd2
--- /dev/null
+++ b/hibernate5/src/test/java/com/baeldung/hibernate/proxy/HibernateProxyUnitTest.java
@@ -0,0 +1,75 @@
+package com.baeldung.hibernate.proxy;
+
+import org.hibernate.*;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.List;
+
+import static org.junit.Assert.fail;
+
+public class HibernateProxyUnitTest {
+
+ private Session session;
+
+ @Before
+ public void init(){
+ try {
+ session = HibernateUtil.getSessionFactory("hibernate.properties")
+ .openSession();
+ } catch (HibernateException | IOException e) {
+ fail("Failed to initiate Hibernate Session [Exception:" + e.toString() + "]");
+ }
+
+ Boss boss = new Boss("Eduard", "Freud");
+ session.save(boss);
+ }
+
+ @After
+ public void close(){
+ if(session != null) {
+ session.close();
+ }
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void givenAnInexistentEmployeeId_whenUseGetMethod_thenReturnNull() {
+ Employee employee = session.get(Employee.class, new Long(14));
+ assertNull(employee);
+ employee.getId();
+ }
+
+ @Test
+ public void givenAnInexistentEmployeeId_whenUseLoadMethod_thenReturnAProxy() {
+ Employee employee = session.load(Employee.class, new Long(14));
+ assertNotNull(employee);
+ }
+
+ @Test
+ public void givenABatchEmployeeList_whenSaveOne_thenSaveTheWholeBatch() {
+ Transaction transaction = session.beginTransaction();
+
+ for (long i = 1; i <= 5; i++) {
+ Employee employee = new Employee();
+ employee.setName("Employee " + i);
+ session.save(employee);
+ }
+
+ //After this line is possible to see all the insertions in the logs
+ session.flush();
+ session.clear();
+ transaction.commit();
+
+ transaction = session.beginTransaction();
+
+ List employeeList = session.createQuery("from Employee")
+ .setCacheMode(CacheMode.IGNORE).getResultList();
+
+ assertEquals(employeeList.size(), 5);
+ transaction.commit();
+ }
+}
diff --git a/java-dates/pom.xml b/java-dates/pom.xml
index 877dd615a8..13e2a077e1 100644
--- a/java-dates/pom.xml
+++ b/java-dates/pom.xml
@@ -61,23 +61,6 @@
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- prepare-package
-
- copy-dependencies
-
-
- ${project.build.directory}/libs
-
-
-
-
-
org.apache.maven.plugins
maven-compiler-plugin
diff --git a/java-numbers/pom.xml b/java-numbers/pom.xml
index bf4d3e8792..bb63c8cfe1 100644
--- a/java-numbers/pom.xml
+++ b/java-numbers/pom.xml
@@ -83,23 +83,6 @@
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- prepare-package
-
- copy-dependencies
-
-
- ${project.build.directory}/libs
-
-
-
-
-
org.apache.maven.plugins
maven-javadoc-plugin
diff --git a/java-numbers/src/main/java/com/baeldung/maths/BigDecimalDemo.java b/java-numbers/src/main/java/com/baeldung/maths/BigDecimalDemo.java
new file mode 100644
index 0000000000..7de0197769
--- /dev/null
+++ b/java-numbers/src/main/java/com/baeldung/maths/BigDecimalDemo.java
@@ -0,0 +1,29 @@
+package com.baeldung.maths;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+public class BigDecimalDemo {
+
+ /** Calculate total amount to be paid for an item rounded to cents..
+ * @param quantity
+ * @param unitPrice
+ * @param discountRate
+ * @param taxRate
+ * @return
+ */
+ public static BigDecimal calculateTotalAmount(BigDecimal quantity,
+ BigDecimal unitPrice, BigDecimal discountRate, BigDecimal taxRate) {
+ BigDecimal amount = quantity.multiply(unitPrice);
+ BigDecimal discount = amount.multiply(discountRate);
+ BigDecimal discountedAmount = amount.subtract(discount);
+ BigDecimal tax = discountedAmount.multiply(taxRate);
+ BigDecimal total = discountedAmount.add(tax);
+
+ // round to 2 decimal places using HALF_EVEN
+ BigDecimal roundedTotal = total.setScale(2, RoundingMode.HALF_EVEN);
+
+ return roundedTotal;
+ }
+
+}
diff --git a/java-numbers/src/test/java/com/baeldung/maths/BigDecimalDemoUnitTest.java b/java-numbers/src/test/java/com/baeldung/maths/BigDecimalDemoUnitTest.java
new file mode 100644
index 0000000000..2bf9872bec
--- /dev/null
+++ b/java-numbers/src/test/java/com/baeldung/maths/BigDecimalDemoUnitTest.java
@@ -0,0 +1,120 @@
+package com.baeldung.maths;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+import java.math.RoundingMode;
+import java.util.Random;
+
+import org.junit.jupiter.api.Test;
+
+public class BigDecimalDemoUnitTest {
+
+ @Test
+ public void whenBigDecimalCreated_thenValueMatches() {
+ BigDecimal bdFromString = new BigDecimal("0.1");
+ BigDecimal bdFromCharArray = new BigDecimal(
+ new char[] { '3', '.', '1', '6', '1', '5' });
+ BigDecimal bdlFromInt = new BigDecimal(42);
+ BigDecimal bdFromLong = new BigDecimal(123412345678901L);
+ BigInteger bigInteger = BigInteger.probablePrime(100, new Random());
+ BigDecimal bdFromBigInteger = new BigDecimal(bigInteger);
+
+ assertEquals("0.1", bdFromString.toString());
+ assertEquals("3.1615", bdFromCharArray.toString());
+ assertEquals("42", bdlFromInt.toString());
+ assertEquals("123412345678901", bdFromLong.toString());
+ assertEquals(bigInteger.toString(), bdFromBigInteger.toString());
+ }
+
+ @Test
+ public void whenBigDecimalCreatedFromDouble_thenValueMayNotMatch() {
+ BigDecimal bdFromDouble = new BigDecimal(0.1d);
+ assertNotEquals("0.1", bdFromDouble.toString());
+ }
+
+ @Test
+ public void whenBigDecimalCreatedUsingValueOf_thenValueMatches() {
+ BigDecimal bdFromLong1 = BigDecimal.valueOf(123412345678901L);
+ BigDecimal bdFromLong2 = BigDecimal.valueOf(123412345678901L, 2);
+ BigDecimal bdFromDouble = BigDecimal.valueOf(0.1d);
+
+ assertEquals("123412345678901", bdFromLong1.toString());
+ assertEquals("1234123456789.01", bdFromLong2.toString());
+ assertEquals("0.1", bdFromDouble.toString());
+ }
+
+ @Test
+ public void whenEqualsCalled_thenSizeAndScaleMatched() {
+ BigDecimal bd1 = new BigDecimal("1.0");
+ BigDecimal bd2 = new BigDecimal("1.00");
+
+ assertFalse(bd1.equals(bd2));
+ }
+
+ @Test
+ public void whenComparingBigDecimals_thenExpectedResult() {
+ BigDecimal bd1 = new BigDecimal("1.0");
+ BigDecimal bd2 = new BigDecimal("1.00");
+ BigDecimal bd3 = new BigDecimal("2.0");
+
+ assertTrue(bd1.compareTo(bd3) < 0);
+ assertTrue(bd3.compareTo(bd1) > 0);
+ assertTrue(bd1.compareTo(bd2) == 0);
+ assertTrue(bd1.compareTo(bd3) <= 0);
+ assertTrue(bd1.compareTo(bd2) >= 0);
+ assertTrue(bd1.compareTo(bd3) != 0);
+ }
+
+ @Test
+ public void whenPerformingArithmetic_thenExpectedResult() {
+ BigDecimal bd1 = new BigDecimal("4.0");
+ BigDecimal bd2 = new BigDecimal("2.0");
+
+ BigDecimal sum = bd1.add(bd2);
+ BigDecimal difference = bd1.subtract(bd2);
+ BigDecimal quotient = bd1.divide(bd2);
+ BigDecimal product = bd1.multiply(bd2);
+
+ assertTrue(sum.compareTo(new BigDecimal("6.0")) == 0);
+ assertTrue(difference.compareTo(new BigDecimal("2.0")) == 0);
+ assertTrue(quotient.compareTo(new BigDecimal("2.0")) == 0);
+ assertTrue(product.compareTo(new BigDecimal("8.0")) == 0);
+ }
+
+ @Test
+ public void whenGettingAttributes_thenExpectedResult() {
+ BigDecimal bd = new BigDecimal("-12345.6789");
+
+ assertEquals(9, bd.precision());
+ assertEquals(4, bd.scale());
+ assertEquals(-1, bd.signum());
+ }
+
+ @Test
+ public void whenRoundingDecimal_thenExpectedResult() {
+ BigDecimal bd = new BigDecimal("2.5");
+ // Round to 1 digit using HALF_EVEN
+ BigDecimal rounded = bd
+ .round(new MathContext(1, RoundingMode.HALF_EVEN));
+
+ assertEquals("2", rounded.toString());
+ }
+
+ @Test
+ public void givenPurchaseTxn_whenCalculatingTotalAmount_thenExpectedResult() {
+ BigDecimal quantity = new BigDecimal("4.5");
+ BigDecimal unitPrice = new BigDecimal("2.69");
+ BigDecimal discountRate = new BigDecimal("0.10");
+ BigDecimal taxRate = new BigDecimal("0.0725");
+
+ BigDecimal amountToBePaid = BigDecimalDemo
+ .calculateTotalAmount(quantity, unitPrice, discountRate, taxRate);
+ assertEquals("11.68", amountToBePaid.toString());
+ }
+}
diff --git a/java-numbers/src/test/java/com/baeldung/maths/BigIntegerDemoUnitTest.java b/java-numbers/src/test/java/com/baeldung/maths/BigIntegerDemoUnitTest.java
new file mode 100644
index 0000000000..3537ccb3a3
--- /dev/null
+++ b/java-numbers/src/test/java/com/baeldung/maths/BigIntegerDemoUnitTest.java
@@ -0,0 +1,128 @@
+package com.baeldung.maths;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigInteger;
+import java.util.Random;
+
+import org.junit.jupiter.api.Test;
+
+public class BigIntegerDemoUnitTest {
+
+ @Test
+ public void whenBigIntegerCreatedFromConstructor_thenExpectedResult() {
+ BigInteger biFromString = new BigInteger("1234567890987654321");
+ BigInteger biFromByteArray = new BigInteger(
+ new byte[] { 64, 64, 64, 64, 64, 64 });
+ BigInteger biFromSignMagnitude = new BigInteger(-1,
+ new byte[] { 64, 64, 64, 64, 64, 64 });
+
+ assertEquals("1234567890987654321", biFromString.toString());
+ assertEquals("70644700037184", biFromByteArray.toString());
+ assertEquals("-70644700037184", biFromSignMagnitude.toString());
+ }
+
+ @Test
+ public void whenLongConvertedToBigInteger_thenValueMatches() {
+ BigInteger bi = BigInteger.valueOf(2305843009213693951L);
+
+ assertEquals("2305843009213693951", bi.toString());
+ }
+
+ @Test
+ public void givenBigIntegers_whentCompared_thenExpectedResult() {
+ BigInteger i = new BigInteger("123456789012345678901234567890");
+ BigInteger j = new BigInteger("123456789012345678901234567891");
+ BigInteger k = new BigInteger("123456789012345678901234567892");
+
+ assertTrue(i.compareTo(i) == 0);
+ assertTrue(j.compareTo(i) > 0);
+ assertTrue(j.compareTo(k) < 0);
+ }
+
+ @Test
+ public void givenBigIntegers_whenPerformingArithmetic_thenExpectedResult() {
+ BigInteger i = new BigInteger("4");
+ BigInteger j = new BigInteger("2");
+
+ BigInteger sum = i.add(j);
+ BigInteger difference = i.subtract(j);
+ BigInteger quotient = i.divide(j);
+ BigInteger product = i.multiply(j);
+
+ assertEquals(new BigInteger("6"), sum);
+ assertEquals(new BigInteger("2"), difference);
+ assertEquals(new BigInteger("2"), quotient);
+ assertEquals(new BigInteger("8"), product);
+ }
+
+ @Test
+ public void givenBigIntegers_whenPerformingBitOperations_thenExpectedResult() {
+ BigInteger i = new BigInteger("17");
+ BigInteger j = new BigInteger("7");
+
+ BigInteger and = i.and(j);
+ BigInteger or = i.or(j);
+ BigInteger not = j.not();
+ BigInteger xor = i.xor(j);
+ BigInteger andNot = i.andNot(j);
+ BigInteger shiftLeft = i.shiftLeft(1);
+ BigInteger shiftRight = i.shiftRight(1);
+
+ assertEquals(new BigInteger("1"), and);
+ assertEquals(new BigInteger("23"), or);
+ assertEquals(new BigInteger("-8"), not);
+ assertEquals(new BigInteger("22"), xor);
+ assertEquals(new BigInteger("16"), andNot);
+ assertEquals(new BigInteger("34"), shiftLeft);
+ assertEquals(new BigInteger("8"), shiftRight);
+ }
+
+ @Test
+ public void givenBigIntegers_whenPerformingBitManipulations_thenExpectedResult() {
+ BigInteger i = new BigInteger("1018");
+
+ int bitCount = i.bitCount();
+ int bitLength = i.bitLength();
+ int getLowestSetBit = i.getLowestSetBit();
+ boolean testBit3 = i.testBit(3);
+ BigInteger setBit12 = i.setBit(12);
+ BigInteger flipBit0 = i.flipBit(0);
+ BigInteger clearBit3 = i.clearBit(3);
+
+ assertEquals(8, bitCount);
+ assertEquals(10, bitLength);
+ assertEquals(1, getLowestSetBit);
+ assertEquals(true, testBit3);
+ assertEquals(new BigInteger("5114"), setBit12);
+ assertEquals(new BigInteger("1019"), flipBit0);
+ assertEquals(new BigInteger("1010"), clearBit3);
+ }
+
+ @Test
+ public void givenBigIntegers_whenModularCalculation_thenExpectedResult() {
+ BigInteger i = new BigInteger("31");
+ BigInteger j = new BigInteger("24");
+ BigInteger k = new BigInteger("16");
+
+ BigInteger gcd = j.gcd(k);
+ BigInteger multiplyAndmod = j.multiply(k)
+ .mod(i);
+ BigInteger modInverse = j.modInverse(i);
+ BigInteger modPow = j.modPow(k, i);
+
+ assertEquals(new BigInteger("8"), gcd);
+ assertEquals(new BigInteger("12"), multiplyAndmod);
+ assertEquals(new BigInteger("22"), modInverse);
+ assertEquals(new BigInteger("7"), modPow);
+ }
+
+ @Test
+ public void givenBigIntegers_whenPrimeOperations_thenExpectedResult() {
+ BigInteger i = BigInteger.probablePrime(100, new Random());
+
+ boolean isProbablePrime = i.isProbablePrime(1000);
+ assertEquals(true, isProbablePrime);
+ }
+}
diff --git a/java-streams/pom.xml b/java-streams/pom.xml
index 4f8651a756..023a5f695b 100644
--- a/java-streams/pom.xml
+++ b/java-streams/pom.xml
@@ -86,23 +86,6 @@
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- prepare-package
-
- copy-dependencies
-
-
- ${project.build.directory}/libs
-
-
-
-
-
org.apache.maven.plugins
maven-compiler-plugin
diff --git a/java-streams/src/test/java/com/baeldung/streamordering/BenchmarkUnitTest.java b/java-streams/src/test/java/com/baeldung/streamordering/BenchmarkManualTest.java
similarity index 98%
rename from java-streams/src/test/java/com/baeldung/streamordering/BenchmarkUnitTest.java
rename to java-streams/src/test/java/com/baeldung/streamordering/BenchmarkManualTest.java
index ba1cb1f726..656a6d95f9 100644
--- a/java-streams/src/test/java/com/baeldung/streamordering/BenchmarkUnitTest.java
+++ b/java-streams/src/test/java/com/baeldung/streamordering/BenchmarkManualTest.java
@@ -15,7 +15,7 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
-public class BenchmarkUnitTest
+public class BenchmarkManualTest
{
public void
diff --git a/java-strings/README.md b/java-strings/README.md
index 04f15136c9..233d986d98 100644
--- a/java-strings/README.md
+++ b/java-strings/README.md
@@ -26,3 +26,4 @@
- [Convert a String to Title Case](http://www.baeldung.com/java-string-title-case)
- [Compact Strings in Java 9](http://www.baeldung.com/java-9-compact-string)
- [Java Check a String for Lowercase/Uppercase Letter, Special Character and Digit](https://www.baeldung.com/java-lowercase-uppercase-special-character-digit-regex)
+- [Convert java.util.Date to String](https://www.baeldung.com/java-util-date-to-string)
diff --git a/java-strings/pom.xml b/java-strings/pom.xml
index 0c83b4d9e7..2afe18f07a 100644
--- a/java-strings/pom.xml
+++ b/java-strings/pom.xml
@@ -71,23 +71,6 @@
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- prepare-package
-
- copy-dependencies
-
-
- ${project.build.directory}/libs
-
-
-
-
-
org.apache.maven.plugins
maven-compiler-plugin
diff --git a/java-strings/src/main/java/com/baeldung/string/JoinerSplitter.java b/java-strings/src/main/java/com/baeldung/string/JoinerSplitter.java
index 085be66801..cdbba1ef53 100644
--- a/java-strings/src/main/java/com/baeldung/string/JoinerSplitter.java
+++ b/java-strings/src/main/java/com/baeldung/string/JoinerSplitter.java
@@ -2,6 +2,7 @@ package com.baeldung.string;
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -32,5 +33,12 @@ public class JoinerSplitter {
.mapToObj(item -> (char) item)
.collect(Collectors.toList());
}
+
+ public static Map arrayToMap(String[] arrayOfString) {
+ return Arrays.asList(arrayOfString)
+ .stream()
+ .map(str -> str.split(":"))
+ .collect(Collectors.toMap(str -> str[0], str -> str[1]));
+ }
}
diff --git a/java-strings/src/test/java/com/baeldung/string/JoinerSplitterUnitTest.java b/java-strings/src/test/java/com/baeldung/string/JoinerSplitterUnitTest.java
index 8901bcf9db..a9488e27a4 100644
--- a/java-strings/src/test/java/com/baeldung/string/JoinerSplitterUnitTest.java
+++ b/java-strings/src/test/java/com/baeldung/string/JoinerSplitterUnitTest.java
@@ -3,7 +3,9 @@ package com.baeldung.string;
import org.junit.Test;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import static org.junit.Assert.assertEquals;
@@ -62,5 +64,20 @@ public class JoinerSplitterUnitTest {
assertEquals(result, expectation);
}
+
+ @Test
+ public void givenStringArray_transformedToStream_convertToMap() {
+
+ String[] programming_languages = new String[] {"language:java","os:linux","editor:emacs"};
+
+ Map expectation=new HashMap<>();
+ expectation.put("language", "java");
+ expectation.put("os", "linux");
+ expectation.put("editor", "emacs");
+
+ Map result = JoinerSplitter.arrayToMap(programming_languages);
+ assertEquals(result, expectation);
+
+ }
}
diff --git a/java-strings/src/test/java/com/baeldung/string/SplitUnitTest.java b/java-strings/src/test/java/com/baeldung/string/SplitUnitTest.java
index 3859a2b26b..6157640a4a 100644
--- a/java-strings/src/test/java/com/baeldung/string/SplitUnitTest.java
+++ b/java-strings/src/test/java/com/baeldung/string/SplitUnitTest.java
@@ -2,10 +2,11 @@ package com.baeldung.string;
import static org.assertj.core.api.Assertions.assertThat;
+import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
import com.google.common.base.Splitter;
@@ -54,4 +55,18 @@ public class SplitUnitTest {
assertThat(resultList)
.containsExactly("car", "jeep", "scooter");
}
+
+ @Test
+ public void givenStringContainsSpaces_whenSplitAndTrim_thenReturnsArray_using_Regex() {
+ assertThat(" car , jeep, scooter ".trim()
+ .split("\\s*,\\s*")).containsExactly("car", "jeep", "scooter");
+
+ }
+
+ @Test
+ public void givenStringContainsSpaces_whenSplitAndTrim_thenReturnsArray_using_java_8() {
+ assertThat(Arrays.stream(" car , jeep, scooter ".split(","))
+ .map(String::trim)
+ .toArray(String[]::new)).containsExactly("car", "jeep", "scooter");
+ }
}
diff --git a/jersey/pom.xml b/jersey/pom.xml
index e248f9cf90..b55bdc5330 100644
--- a/jersey/pom.xml
+++ b/jersey/pom.xml
@@ -39,6 +39,11 @@
jersey-mvc-freemarker
${jersey.version}
+
+ org.glassfish.jersey.ext
+ jersey-bean-validation
+ ${jersey.version}
+
org.glassfish.jersey.test-framework
jersey-test-framework-core
diff --git a/jersey/src/main/java/com/baeldung/jersey/server/config/ViewApplicationConfig.java b/jersey/src/main/java/com/baeldung/jersey/server/config/ViewApplicationConfig.java
index d4744066c4..b6b9853aae 100644
--- a/jersey/src/main/java/com/baeldung/jersey/server/config/ViewApplicationConfig.java
+++ b/jersey/src/main/java/com/baeldung/jersey/server/config/ViewApplicationConfig.java
@@ -1,12 +1,14 @@
package com.baeldung.jersey.server.config;
import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
import org.glassfish.jersey.server.mvc.freemarker.FreemarkerMvcFeature;
public class ViewApplicationConfig extends ResourceConfig {
public ViewApplicationConfig() {
packages("com.baeldung.jersey.server");
+ property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
property(FreemarkerMvcFeature.TEMPLATE_BASE_PATH, "templates/freemarker");
register(FreemarkerMvcFeature.class);;
}
diff --git a/jersey/src/main/java/com/baeldung/jersey/server/constraints/SerialNumber.java b/jersey/src/main/java/com/baeldung/jersey/server/constraints/SerialNumber.java
new file mode 100644
index 0000000000..ca49797e31
--- /dev/null
+++ b/jersey/src/main/java/com/baeldung/jersey/server/constraints/SerialNumber.java
@@ -0,0 +1,35 @@
+package com.baeldung.jersey.server.constraints;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.regex.Pattern;
+
+import javax.validation.Constraint;
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import javax.validation.Payload;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = { SerialNumber.Validator.class })
+public @interface SerialNumber {
+
+ String message()
+
+ default "Fruit serial number is not valid";
+
+ Class>[] groups() default {};
+
+ Class extends Payload>[] payload() default {};
+
+ public class Validator implements ConstraintValidator {
+ @Override
+ public void initialize(final SerialNumber serial) {
+ }
+
+ @Override
+ public boolean isValid(final String serial, final ConstraintValidatorContext constraintValidatorContext) {
+ final String serialNumRegex = "^\\d{3}-\\d{3}-\\d{4}$";
+ return Pattern.matches(serialNumRegex, serial);
+ }
+ }
+}
diff --git a/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java b/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java
index 30620e331d..c55362487b 100644
--- a/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java
+++ b/jersey/src/main/java/com/baeldung/jersey/server/model/Fruit.java
@@ -1,20 +1,57 @@
package com.baeldung.jersey.server.model;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
public class Fruit {
- private final String name;
- private final String colour;
+ @Min(value = 10, message = "Fruit weight must be 10 or greater")
+ private Integer weight;
+ @Size(min = 5, max = 200)
+ private String name;
+ @Size(min = 5, max = 200)
+ private String colour;
+ private String serial;
+
+ public Fruit() {
+ }
public Fruit(String name, String colour) {
this.name = name;
this.colour = colour;
}
-
+
public String getName() {
return name;
}
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setColour(String colour) {
+ this.colour = colour;
+ }
public String getColour() {
return colour;
}
+
+ public Integer getWeight() {
+ return weight;
+ }
+
+ public void setWeight(Integer weight) {
+ this.weight = weight;
+ }
+
+ public String getSerial() {
+ return serial;
+ }
+
+ public void setSerial(String serial) {
+ this.serial = serial;
+ }
}
diff --git a/jersey/src/main/java/com/baeldung/jersey/server/providers/FruitExceptionMapper.java b/jersey/src/main/java/com/baeldung/jersey/server/providers/FruitExceptionMapper.java
new file mode 100644
index 0000000000..cea61c897b
--- /dev/null
+++ b/jersey/src/main/java/com/baeldung/jersey/server/providers/FruitExceptionMapper.java
@@ -0,0 +1,26 @@
+package com.baeldung.jersey.server.providers;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+
+public class FruitExceptionMapper implements ExceptionMapper {
+
+ @Override
+ public Response toResponse(final ConstraintViolationException exception) {
+ return Response.status(Response.Status.BAD_REQUEST)
+ .entity(prepareMessage(exception))
+ .type("text/plain")
+ .build();
+ }
+
+ private String prepareMessage(ConstraintViolationException exception) {
+ final StringBuilder message = new StringBuilder();
+ for (ConstraintViolation> cv : exception.getConstraintViolations()) {
+ message.append(cv.getPropertyPath() + " " + cv.getMessage() + "\n");
+ }
+ return message.toString();
+ }
+
+}
diff --git a/jersey/src/main/java/com/baeldung/jersey/server/rest/FruitResource.java b/jersey/src/main/java/com/baeldung/jersey/server/rest/FruitResource.java
index 4e1fa4aa11..ee34cdd3ca 100644
--- a/jersey/src/main/java/com/baeldung/jersey/server/rest/FruitResource.java
+++ b/jersey/src/main/java/com/baeldung/jersey/server/rest/FruitResource.java
@@ -5,7 +5,13 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@@ -15,7 +21,9 @@ import org.glassfish.jersey.server.mvc.ErrorTemplate;
import org.glassfish.jersey.server.mvc.Template;
import org.glassfish.jersey.server.mvc.Viewable;
+import com.baeldung.jersey.server.constraints.SerialNumber;
import com.baeldung.jersey.server.model.Fruit;
+import com.baeldung.jersey.service.SimpleStorageService;
@Path("/fruit")
public class FruitResource {
@@ -52,4 +60,49 @@ public class FruitResource {
return name;
}
+ @POST
+ @Path("/create")
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public void createFruit(
+ @NotNull(message = "Fruit name must not be null") @FormParam("name") String name,
+ @NotNull(message = "Fruit colour must not be null") @FormParam("colour") String colour) {
+
+ Fruit fruit = new Fruit(name, colour);
+ SimpleStorageService.storeFruit(fruit);
+ }
+
+ @PUT
+ @Path("/update")
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public void updateFruit(@SerialNumber @FormParam("serial") String serial) {
+ Fruit fruit = new Fruit();
+ fruit.setSerial(serial);
+ SimpleStorageService.storeFruit(fruit);
+ }
+
+ @POST
+ @Path("/create")
+ @Consumes(MediaType.APPLICATION_JSON)
+ public void createFruit(@Valid Fruit fruit) {
+ SimpleStorageService.storeFruit(fruit);
+ }
+
+ @GET
+ @Valid
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("/search/{name}")
+ public Fruit findFruitByName(@PathParam("name") String name) {
+ return SimpleStorageService.findByName(name);
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_HTML)
+ @Path("/exception")
+ @Valid
+ public Fruit exception() {
+ Fruit fruit = new Fruit();
+ fruit.setName("a");
+ fruit.setColour("b");
+ return fruit;
+ }
}
diff --git a/jersey/src/main/java/com/baeldung/jersey/service/SimpleStorageService.java b/jersey/src/main/java/com/baeldung/jersey/service/SimpleStorageService.java
new file mode 100644
index 0000000000..e21dd584a1
--- /dev/null
+++ b/jersey/src/main/java/com/baeldung/jersey/service/SimpleStorageService.java
@@ -0,0 +1,25 @@
+package com.baeldung.jersey.service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.baeldung.jersey.server.model.Fruit;
+
+public class SimpleStorageService {
+
+ private static final Map fruits = new HashMap();
+
+ public static void storeFruit(final Fruit fruit) {
+ fruits.put(fruit.getName(), fruit);
+ }
+
+ public static Fruit findByName(final String name) {
+ return fruits.entrySet()
+ .stream()
+ .filter(map -> name.equals(map.getKey()))
+ .map(map -> map.getValue())
+ .findFirst()
+ .get();
+ }
+
+}
diff --git a/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java b/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java
index a0b6daed51..2eeb5710cb 100644
--- a/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java
+++ b/jersey/src/test/java/com/baeldung/jersey/server/rest/FruitResourceIntegrationTest.java
@@ -2,41 +2,116 @@ package com.baeldung.jersey.server.rest;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
import org.glassfish.jersey.test.JerseyTest;
-import org.junit.Assert;
+import org.glassfish.jersey.test.TestProperties;
import org.junit.Test;
import com.baeldung.jersey.server.config.ViewApplicationConfig;
+import com.baeldung.jersey.server.model.Fruit;
+import com.baeldung.jersey.server.providers.FruitExceptionMapper;
public class FruitResourceIntegrationTest extends JerseyTest {
@Override
protected Application configure() {
- return new ViewApplicationConfig();
+ enable(TestProperties.LOG_TRAFFIC);
+ enable(TestProperties.DUMP_ENTITY);
+
+ ViewApplicationConfig config = new ViewApplicationConfig();
+ config.register(FruitExceptionMapper.class);
+ return config;
}
@Test
- public void testAllFruit() {
+ public void givenGetAllFruit_whenCorrectRequest_thenAllTemplateInvoked() {
final String response = target("/fruit/all").request()
.get(String.class);
- Assert.assertThat(response, allOf(containsString("banana"), containsString("apple"), containsString("kiwi")));
+ assertThat(response, allOf(containsString("banana"), containsString("apple"), containsString("kiwi")));
}
@Test
- public void testIndex() {
+ public void givenGetFruit_whenCorrectRequest_thenIndexTemplateInvoked() {
final String response = target("/fruit").request()
.get(String.class);
- Assert.assertThat(response, containsString("Welcome Fruit Index Page!"));
+ assertThat(response, containsString("Welcome Fruit Index Page!"));
}
@Test
- public void testErrorTemplate() {
+ public void givenGetFruitByName_whenFruitUnknown_thenErrorTemplateInvoked() {
final String response = target("/fruit/orange").request()
.get(String.class);
- Assert.assertThat(response, containsString("Error - Fruit not found: orange!"));
+ assertThat(response, containsString("Error - Fruit not found: orange!"));
+ }
+
+ @Test
+ public void givenCreateFruit_whenFormContainsNullParam_thenResponseCodeIsBadRequest() {
+ Form form = new Form();
+ form.param("name", "apple");
+ form.param("colour", null);
+ Response response = target("fruit/create").request(MediaType.APPLICATION_FORM_URLENCODED)
+ .post(Entity.form(form));
+
+ assertEquals("Http Response should be 400 ", 400, response.getStatus());
+ assertThat(response.readEntity(String.class), containsString("Fruit colour must not be null"));
+ }
+
+ @Test
+ public void givenUpdateFruit_whenFormContainsBadSerialParam_thenResponseCodeIsBadRequest() {
+ Form form = new Form();
+ form.param("serial", "2345-2345");
+
+ Response response = target("fruit/update").request(MediaType.APPLICATION_FORM_URLENCODED)
+ .put(Entity.form(form));
+
+ assertEquals("Http Response should be 400 ", 400, response.getStatus());
+ assertThat(response.readEntity(String.class), containsString("Fruit serial number is not valid"));
+ }
+
+ @Test
+ public void givenCreateFruit_whenFruitIsInvalid_thenResponseCodeIsBadRequest() {
+ Fruit fruit = new Fruit("Blueberry", "purple");
+ fruit.setWeight(1);
+
+ Response response = target("fruit/create").request(MediaType.APPLICATION_JSON_TYPE)
+ .post(Entity.entity(fruit, MediaType.APPLICATION_JSON_TYPE));
+
+ assertEquals("Http Response should be 400 ", 400, response.getStatus());
+ assertThat(response.readEntity(String.class), containsString("Fruit weight must be 10 or greater"));
+ }
+
+ @Test
+ public void givenFruitExists_whenSearching_thenResponseContainsFruit() {
+ Fruit fruit = new Fruit();
+ fruit.setName("strawberry");
+ fruit.setWeight(20);
+ Response response = target("fruit/create").request(MediaType.APPLICATION_JSON_TYPE)
+ .post(Entity.entity(fruit, MediaType.APPLICATION_JSON_TYPE));
+
+ assertEquals("Http Response should be 204 ", 204, response.getStatus());
+
+ final String json = target("fruit/search/strawberry").request()
+ .get(String.class);
+ assertThat(json, containsString("{\"name\":\"strawberry\",\"weight\":20}"));
+ }
+
+ @Test
+ public void givenFruit_whenFruitIsInvalid_thenReponseContainsCustomExceptions() {
+ final Response response = target("fruit/exception").request()
+ .get();
+
+ assertEquals("Http Response should be 400 ", 400, response.getStatus());
+ String responseString = response.readEntity(String.class);
+ assertThat(responseString, containsString("exception..colour size must be between 5 and 200"));
+ assertThat(responseString, containsString("exception..name size must be between 5 and 200"));
}
}
diff --git a/jta/pom.xml b/jta/pom.xml
new file mode 100644
index 0000000000..89bdccf25e
--- /dev/null
+++ b/jta/pom.xml
@@ -0,0 +1,88 @@
+
+
+ 4.0.0
+ com.baeldung
+ jta-demo
+ 1.0-SNAPSHOT
+ jar
+
+ JEE JTA demo
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.4.RELEASE
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jta-bitronix
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.hsqldb
+ hsqldb
+ 2.4.1
+
+
+
+
+
+ autoconfiguration
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ integration-test
+
+ test
+
+
+
+ **/*LiveTest.java
+ **/*IntegrationTest.java
+ **/*IntTest.java
+
+
+ **/AutoconfigurationTest.java
+
+
+
+
+
+
+ json
+
+
+
+
+
+
+
+
diff --git a/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java b/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java
new file mode 100644
index 0000000000..4d8779efe5
--- /dev/null
+++ b/jta/src/main/java/com/baeldung/jtademo/JtaDemoApplication.java
@@ -0,0 +1,48 @@
+package com.baeldung.jtademo;
+
+import org.hsqldb.jdbc.pool.JDBCXADataSource;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.jta.bitronix.BitronixXADataSourceWrapper;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.sql.DataSource;
+
+@EnableAutoConfiguration
+@EnableTransactionManagement
+@Configuration
+@ComponentScan
+public class JtaDemoApplication {
+
+ @Bean("dataSourceAccount")
+ public DataSource dataSource() throws Exception {
+ return createHsqlXADatasource("jdbc:hsqldb:mem:accountDb");
+ }
+
+ @Bean("dataSourceAudit")
+ public DataSource dataSourceAudit() throws Exception {
+ return createHsqlXADatasource("jdbc:hsqldb:mem:auditDb");
+ }
+
+ private DataSource createHsqlXADatasource(String connectionUrl) throws Exception {
+ JDBCXADataSource dataSource = new JDBCXADataSource();
+ dataSource.setUrl(connectionUrl);
+ dataSource.setUser("sa");
+ BitronixXADataSourceWrapper wrapper = new BitronixXADataSourceWrapper();
+ return wrapper.wrapDataSource(dataSource);
+ }
+
+ @Bean("jdbcTemplateAccount")
+ public JdbcTemplate jdbcTemplate(@Qualifier("dataSourceAccount") DataSource dataSource) {
+ return new JdbcTemplate(dataSource);
+ }
+
+ @Bean("jdbcTemplateAudit")
+ public JdbcTemplate jdbcTemplateAudit(@Qualifier("dataSourceAudit") DataSource dataSource) {
+ return new JdbcTemplate(dataSource);
+ }
+}
diff --git a/jta/src/main/java/com/baeldung/jtademo/dto/TransferLog.java b/jta/src/main/java/com/baeldung/jtademo/dto/TransferLog.java
new file mode 100644
index 0000000000..cc1474ce81
--- /dev/null
+++ b/jta/src/main/java/com/baeldung/jtademo/dto/TransferLog.java
@@ -0,0 +1,27 @@
+package com.baeldung.jtademo.dto;
+
+import java.math.BigDecimal;
+
+public class TransferLog {
+ private String fromAccountId;
+ private String toAccountId;
+ private BigDecimal amount;
+
+ public TransferLog(String fromAccountId, String toAccountId, BigDecimal amount) {
+ this.fromAccountId = fromAccountId;
+ this.toAccountId = toAccountId;
+ this.amount = amount;
+ }
+
+ public String getFromAccountId() {
+ return fromAccountId;
+ }
+
+ public String getToAccountId() {
+ return toAccountId;
+ }
+
+ public BigDecimal getAmount() {
+ return amount;
+ }
+}
diff --git a/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java b/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java
new file mode 100644
index 0000000000..f6810e15c8
--- /dev/null
+++ b/jta/src/main/java/com/baeldung/jtademo/services/AuditService.java
@@ -0,0 +1,33 @@
+package com.baeldung.jtademo.services;
+
+import com.baeldung.jtademo.dto.TransferLog;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.ResultSetExtractor;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+
+@Service
+public class AuditService {
+
+ final JdbcTemplate jdbcTemplate;
+
+ @Autowired
+ public AuditService(@Qualifier("jdbcTemplateAudit") JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+
+ public void log(String fromAccount, String toAccount, BigDecimal amount) {
+ jdbcTemplate.update("insert into AUDIT_LOG(FROM_ACCOUNT, TO_ACCOUNT, AMOUNT) values ?,?,?", fromAccount, toAccount, amount);
+ }
+
+ public TransferLog lastTransferLog() {
+ return jdbcTemplate.query("select FROM_ACCOUNT,TO_ACCOUNT,AMOUNT from AUDIT_LOG order by ID desc", (ResultSetExtractor) (rs) -> {
+ if (!rs.next())
+ return null;
+ return new TransferLog(rs.getString(1), rs.getString(2), BigDecimal.valueOf(rs.getDouble(3)));
+ });
+ }
+}
diff --git a/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java b/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java
new file mode 100644
index 0000000000..0c881edbaa
--- /dev/null
+++ b/jta/src/main/java/com/baeldung/jtademo/services/BankAccountService.java
@@ -0,0 +1,32 @@
+package com.baeldung.jtademo.services;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.ResultSetExtractor;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+
+@Service
+public class BankAccountService {
+
+ final JdbcTemplate jdbcTemplate;
+
+ @Autowired
+ public BankAccountService(@Qualifier("jdbcTemplateAccount") JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+
+ public void transfer(String fromAccountId, String toAccountId, BigDecimal amount) {
+ jdbcTemplate.update("update ACCOUNT set BALANCE=BALANCE-? where ID=?", amount, fromAccountId);
+ jdbcTemplate.update("update ACCOUNT set BALANCE=BALANCE+? where ID=?", amount, toAccountId);
+ }
+
+ public BigDecimal balanceOf(String accountId) {
+ return jdbcTemplate.query("select BALANCE from ACCOUNT where ID=?", new Object[] { accountId }, (ResultSetExtractor) (rs) -> {
+ rs.next();
+ return new BigDecimal(rs.getDouble(1));
+ });
+ }
+}
diff --git a/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java b/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java
new file mode 100644
index 0000000000..d3bd80a2ee
--- /dev/null
+++ b/jta/src/main/java/com/baeldung/jtademo/services/TellerService.java
@@ -0,0 +1,45 @@
+package com.baeldung.jtademo.services;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.transaction.Transactional;
+import javax.transaction.UserTransaction;
+import java.math.BigDecimal;
+
+@Service
+public class TellerService {
+ private final BankAccountService bankAccountService;
+ private final AuditService auditService;
+ private final UserTransaction userTransaction;
+
+ @Autowired
+ public TellerService(BankAccountService bankAccountService, AuditService auditService, UserTransaction userTransaction) {
+ this.bankAccountService = bankAccountService;
+ this.auditService = auditService;
+ this.userTransaction = userTransaction;
+ }
+
+ @Transactional
+ public void executeTransfer(String fromAccontId, String toAccountId, BigDecimal amount) {
+ bankAccountService.transfer(fromAccontId, toAccountId, amount);
+ auditService.log(fromAccontId, toAccountId, amount);
+ BigDecimal balance = bankAccountService.balanceOf(fromAccontId);
+ if (balance.compareTo(BigDecimal.ZERO) <= 0) {
+ throw new RuntimeException("Insufficient fund.");
+ }
+ }
+
+ public void executeTransferProgrammaticTx(String fromAccontId, String toAccountId, BigDecimal amount) throws Exception {
+ userTransaction.begin();
+ bankAccountService.transfer(fromAccontId, toAccountId, amount);
+ auditService.log(fromAccontId, toAccountId, amount);
+ BigDecimal balance = bankAccountService.balanceOf(fromAccontId);
+ if (balance.compareTo(BigDecimal.ZERO) <= 0) {
+ userTransaction.rollback();
+ throw new RuntimeException("Insufficient fund.");
+ } else {
+ userTransaction.commit();
+ }
+ }
+}
diff --git a/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java b/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java
new file mode 100644
index 0000000000..c1e8e355ec
--- /dev/null
+++ b/jta/src/main/java/com/baeldung/jtademo/services/TestHelper.java
@@ -0,0 +1,43 @@
+package com.baeldung.jtademo.services;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.core.io.DefaultResourceLoader;
+import org.springframework.core.io.Resource;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.init.ScriptUtils;
+import org.springframework.stereotype.Component;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+@Component
+public class TestHelper {
+ final JdbcTemplate jdbcTemplateAccount;
+
+ final JdbcTemplate jdbcTemplateAudit;
+
+ @Autowired
+ public TestHelper(@Qualifier("jdbcTemplateAccount") JdbcTemplate jdbcTemplateAccount, @Qualifier("jdbcTemplateAudit") JdbcTemplate jdbcTemplateAudit) {
+ this.jdbcTemplateAccount = jdbcTemplateAccount;
+ this.jdbcTemplateAudit = jdbcTemplateAudit;
+ }
+
+ public void runAccountDbInit() throws SQLException {
+ runScript("account.sql", jdbcTemplateAccount.getDataSource());
+ }
+
+ public void runAuditDbInit() throws SQLException {
+ runScript("audit.sql", jdbcTemplateAudit.getDataSource());
+ }
+
+ private void runScript(String scriptName, DataSource dataSouorce) throws SQLException {
+ DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
+ Resource script = resourceLoader.getResource(scriptName);
+ try (Connection con = dataSouorce.getConnection()) {
+ ScriptUtils.executeSqlScript(con, script);
+ }
+ }
+
+}
diff --git a/jta/src/main/resources/account.sql b/jta/src/main/resources/account.sql
new file mode 100644
index 0000000000..af14f89b01
--- /dev/null
+++ b/jta/src/main/resources/account.sql
@@ -0,0 +1,9 @@
+DROP SCHEMA PUBLIC CASCADE;
+
+create table ACCOUNT (
+ID char(8) PRIMARY KEY,
+BALANCE NUMERIC(28,10)
+);
+
+insert into ACCOUNT(ID, BALANCE) values ('a0000001', 1000);
+insert into ACCOUNT(ID, BALANCE) values ('a0000002', 2000);
\ No newline at end of file
diff --git a/jta/src/main/resources/application.properties b/jta/src/main/resources/application.properties
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/jta/src/main/resources/audit.sql b/jta/src/main/resources/audit.sql
new file mode 100644
index 0000000000..aa5845f402
--- /dev/null
+++ b/jta/src/main/resources/audit.sql
@@ -0,0 +1,8 @@
+DROP SCHEMA PUBLIC CASCADE;
+
+create table AUDIT_LOG (
+ID INTEGER IDENTITY PRIMARY KEY,
+FROM_ACCOUNT varchar(8),
+TO_ACCOUNT varchar(8),
+AMOUNT numeric(28,10)
+);
\ No newline at end of file
diff --git a/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java b/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java
new file mode 100644
index 0000000000..3f6004262b
--- /dev/null
+++ b/jta/src/test/java/com/baeldung/jtademo/JtaDemoUnitTest.java
@@ -0,0 +1,91 @@
+package com.baeldung.jtademo;
+
+import com.baeldung.jtademo.dto.TransferLog;
+import com.baeldung.jtademo.services.AuditService;
+import com.baeldung.jtademo.services.BankAccountService;
+import com.baeldung.jtademo.services.TellerService;
+import com.baeldung.jtademo.services.TestHelper;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.math.BigDecimal;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = JtaDemoApplication.class)
+public class JtaDemoUnitTest {
+ @Autowired
+ TestHelper testHelper;
+
+ @Autowired
+ TellerService tellerService;
+
+ @Autowired
+ BankAccountService accountService;
+
+ @Autowired
+ AuditService auditService;
+
+ @Before
+ public void beforeTest() throws Exception {
+ testHelper.runAuditDbInit();
+ testHelper.runAccountDbInit();
+ }
+
+ @Test
+ public void givenAnnotationTx_whenNoException_thenAllCommitted() throws Exception {
+ tellerService.executeTransfer("a0000001", "a0000002", BigDecimal.valueOf(500));
+
+ assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(500));
+ assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2500));
+
+ TransferLog lastTransferLog = auditService.lastTransferLog();
+ assertThat(lastTransferLog).isNotNull();
+ assertThat(lastTransferLog.getFromAccountId()).isEqualTo("a0000001");
+ assertThat(lastTransferLog.getToAccountId()).isEqualTo("a0000002");
+ assertThat(lastTransferLog.getAmount()).isEqualByComparingTo(BigDecimal.valueOf(500));
+ }
+
+ @Test
+ public void givenAnnotationTx_whenException_thenAllRolledBack() throws Exception {
+ assertThatThrownBy(() -> {
+ tellerService.executeTransfer("a0000002", "a0000001", BigDecimal.valueOf(100000));
+ }).hasMessage("Insufficient fund.");
+
+ assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(1000));
+ assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2000));
+ assertThat(auditService.lastTransferLog()).isNull();
+ }
+
+ @Test
+ public void givenProgrammaticTx_whenCommit_thenAllCommitted() throws Exception {
+ tellerService.executeTransferProgrammaticTx("a0000001", "a0000002", BigDecimal.valueOf(500));
+
+ BigDecimal result = accountService.balanceOf("a0000001");
+ assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(500));
+ assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2500));
+
+ TransferLog lastTransferLog = auditService.lastTransferLog();
+ assertThat(lastTransferLog).isNotNull();
+ assertThat(lastTransferLog.getFromAccountId()).isEqualTo("a0000001");
+ assertThat(lastTransferLog.getToAccountId()).isEqualTo("a0000002");
+ assertThat(lastTransferLog.getAmount()).isEqualByComparingTo(BigDecimal.valueOf(500));
+ }
+
+ @Test
+ public void givenProgrammaticTx_whenRollback_thenAllRolledBack() throws Exception {
+ assertThatThrownBy(() -> {
+ tellerService.executeTransferProgrammaticTx("a0000002", "a0000001", BigDecimal.valueOf(100000));
+ }).hasMessage("Insufficient fund.");
+
+ assertThat(accountService.balanceOf("a0000001")).isEqualByComparingTo(BigDecimal.valueOf(1000));
+ assertThat(accountService.balanceOf("a0000002")).isEqualByComparingTo(BigDecimal.valueOf(2000));
+ assertThat(auditService.lastTransferLog()).isNull();
+ }
+}
diff --git a/core-kotlin/kotlin-ktor/.gitignore b/kotlin-libraries/.gitignore
similarity index 100%
rename from core-kotlin/kotlin-ktor/.gitignore
rename to kotlin-libraries/.gitignore
diff --git a/kotlin-libraries/README.md b/kotlin-libraries/README.md
new file mode 100644
index 0000000000..ce30c71792
--- /dev/null
+++ b/kotlin-libraries/README.md
@@ -0,0 +1,10 @@
+## Relevant articles:
+
+- [Kotlin with Mockito](http://www.baeldung.com/kotlin-mockito)
+- [HTTP Requests with Kotlin and khttp](http://www.baeldung.com/kotlin-khttp)
+- [Kotlin Dependency Injection with Kodein](http://www.baeldung.com/kotlin-kodein-dependency-injection)
+- [Writing Specifications with Kotlin and Spek](http://www.baeldung.com/kotlin-spek)
+- [Processing JSON with Kotlin and Klaxson](http://www.baeldung.com/kotlin-json-klaxson)
+- [Kotlin with Ktor](http://www.baeldung.com/kotlin-ktor)
+- [Idiomatic Logging in Kotlin](http://www.baeldung.com/kotlin-logging)
+- [Guide to the Kotlin Exposed Framework](https://www.baeldung.com/kotlin-exposed-persistence)
\ No newline at end of file
diff --git a/core-kotlin/kotlin-ktor/build.gradle b/kotlin-libraries/build.gradle
old mode 100755
new mode 100644
similarity index 83%
rename from core-kotlin/kotlin-ktor/build.gradle
rename to kotlin-libraries/build.gradle
index 5c8f523cf1..b244df34b0
--- a/core-kotlin/kotlin-ktor/build.gradle
+++ b/kotlin-libraries/build.gradle
@@ -1,47 +1,57 @@
-
-
-group 'com.baeldung.ktor'
-version '1.0-SNAPSHOT'
-
-
-buildscript {
- ext.kotlin_version = '1.2.41'
- ext.ktor_version = '0.9.2'
-
- repositories {
- mavenCentral()
- }
- dependencies {
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- }
-}
-
-apply plugin: 'java'
-apply plugin: 'kotlin'
-apply plugin: 'application'
-
-mainClassName = 'APIServer.kt'
-
-sourceCompatibility = 1.8
-compileKotlin { kotlinOptions.jvmTarget = "1.8" }
-compileTestKotlin { kotlinOptions.jvmTarget = "1.8" }
-
-kotlin { experimental { coroutines "enable" } }
-
-repositories {
- mavenCentral()
- jcenter()
- maven { url "https://dl.bintray.com/kotlin/ktor" }
-}
-
-dependencies {
- compile "io.ktor:ktor-server-netty:$ktor_version"
- compile "ch.qos.logback:logback-classic:1.2.1"
- compile "io.ktor:ktor-gson:$ktor_version"
- testCompile group: 'junit', name: 'junit', version: '4.12'
-
-}
-task runServer(type: JavaExec) {
- main = 'APIServer'
- classpath = sourceSets.main.runtimeClasspath
+
+
+group 'com.baeldung.ktor'
+version '1.0-SNAPSHOT'
+
+
+buildscript {
+ ext.kotlin_version = '1.2.41'
+ ext.ktor_version = '0.9.2'
+
+ repositories {
+ mavenCentral()
+ }
+ dependencies {
+
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+apply plugin: 'java'
+apply plugin: 'kotlin'
+apply plugin: 'application'
+
+mainClassName = 'APIServer.kt'
+
+sourceCompatibility = 1.8
+compileKotlin { kotlinOptions.jvmTarget = "1.8" }
+compileTestKotlin { kotlinOptions.jvmTarget = "1.8" }
+
+kotlin { experimental { coroutines "enable" } }
+
+repositories {
+ mavenCentral()
+ jcenter()
+ maven { url "https://dl.bintray.com/kotlin/ktor" }
+}
+sourceSets {
+ main{
+ kotlin{
+ srcDirs 'com/baeldung/ktor'
+ }
+ }
+
+}
+
+dependencies {
+ compile "io.ktor:ktor-server-netty:$ktor_version"
+ compile "ch.qos.logback:logback-classic:1.2.1"
+ compile "io.ktor:ktor-gson:$ktor_version"
+ testCompile group: 'junit', name: 'junit', version: '4.12'
+ implementation 'com.beust:klaxon:3.0.1'
+
+}
+task runServer(type: JavaExec) {
+ main = 'APIServer'
+ classpath = sourceSets.main.runtimeClasspath
}
\ No newline at end of file
diff --git a/core-kotlin/kotlin-ktor/gradle/wrapper/gradle-wrapper.jar b/kotlin-libraries/gradle/wrapper/gradle-wrapper.jar
old mode 100755
new mode 100644
similarity index 100%
rename from core-kotlin/kotlin-ktor/gradle/wrapper/gradle-wrapper.jar
rename to kotlin-libraries/gradle/wrapper/gradle-wrapper.jar
diff --git a/core-kotlin/kotlin-ktor/gradle/wrapper/gradle-wrapper.properties b/kotlin-libraries/gradle/wrapper/gradle-wrapper.properties
old mode 100755
new mode 100644
similarity index 97%
rename from core-kotlin/kotlin-ktor/gradle/wrapper/gradle-wrapper.properties
rename to kotlin-libraries/gradle/wrapper/gradle-wrapper.properties
index 0b83b5a3e3..933b6473ce
--- a/core-kotlin/kotlin-ktor/gradle/wrapper/gradle-wrapper.properties
+++ b/kotlin-libraries/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip
diff --git a/core-kotlin/kotlin-ktor/gradlew b/kotlin-libraries/gradlew
old mode 100755
new mode 100644
similarity index 100%
rename from core-kotlin/kotlin-ktor/gradlew
rename to kotlin-libraries/gradlew
diff --git a/core-kotlin/kotlin-ktor/gradlew.bat b/kotlin-libraries/gradlew.bat
old mode 100755
new mode 100644
similarity index 96%
rename from core-kotlin/kotlin-ktor/gradlew.bat
rename to kotlin-libraries/gradlew.bat
index e95643d6a2..f9553162f1
--- a/core-kotlin/kotlin-ktor/gradlew.bat
+++ b/kotlin-libraries/gradlew.bat
@@ -1,84 +1,84 @@
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto init
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/kotlin-libraries/pom.xml b/kotlin-libraries/pom.xml
new file mode 100644
index 0000000000..c5b7fed951
--- /dev/null
+++ b/kotlin-libraries/pom.xml
@@ -0,0 +1,105 @@
+
+
+ 4.0.0
+ kotlin-libraries
+ jar
+
+
+ com.baeldung
+ parent-kotlin
+ 1.0.0-SNAPSHOT
+ ../parent-kotlin
+
+
+
+
+ exposed
+ exposed
+ https://dl.bintray.com/kotlin/exposed
+
+
+
+
+
+ org.jetbrains.spek
+ spek-api
+ 1.1.5
+ test
+
+
+ org.jetbrains.spek
+ spek-subject-extension
+ 1.1.5
+ test
+
+
+ org.jetbrains.spek
+ spek-junit-platform-engine
+ 1.1.5
+ test
+
+
+ org.apache.commons
+ commons-math3
+ ${commons-math3.version}
+
+
+ org.junit.platform
+ junit-platform-runner
+ ${junit.platform.version}
+ test
+
+
+ khttp
+ khttp
+ ${khttp.version}
+
+
+ com.nhaarman
+ mockito-kotlin
+ ${mockito-kotlin.version}
+ test
+
+
+ com.github.salomonbrys.kodein
+ kodein
+ ${kodein.version}
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+ com.beust
+ klaxon
+ ${klaxon.version}
+
+
+ org.jetbrains.exposed
+ exposed
+ ${exposed.version}
+
+
+ com.h2database
+ h2
+ ${h2database.version}
+
+
+
+
+ 1.5.0
+ 4.1.0
+ 3.0.4
+ 0.1.0
+ 3.6.1
+ 1.1.1
+ 5.2.0
+ 3.10.0
+ 1.4.197
+ 0.10.4
+
+
+
\ No newline at end of file
diff --git a/core-kotlin/kotlin-ktor/resources/logback.xml b/kotlin-libraries/resources/logback.xml
old mode 100755
new mode 100644
similarity index 96%
rename from core-kotlin/kotlin-ktor/resources/logback.xml
rename to kotlin-libraries/resources/logback.xml
index 274cdcdb02..9452207268
--- a/core-kotlin/kotlin-ktor/resources/logback.xml
+++ b/kotlin-libraries/resources/logback.xml
@@ -1,11 +1,11 @@
-
-
-
- %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
-
-
-
-
-
-
+
+
+
+ %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-kotlin/kotlin-ktor/settings.gradle b/kotlin-libraries/settings.gradle
old mode 100755
new mode 100644
similarity index 94%
rename from core-kotlin/kotlin-ktor/settings.gradle
rename to kotlin-libraries/settings.gradle
index 13bbce9583..c91c993971
--- a/core-kotlin/kotlin-ktor/settings.gradle
+++ b/kotlin-libraries/settings.gradle
@@ -1,2 +1,2 @@
-rootProject.name = 'KtorWithKotlin'
-
+rootProject.name = 'KtorWithKotlin'
+
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/klaxon/CustomProduct.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/CustomProduct.kt
similarity index 100%
rename from core-kotlin/src/main/kotlin/com/baeldung/klaxon/CustomProduct.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/CustomProduct.kt
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/klaxon/Product.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/Product.kt
similarity index 100%
rename from core-kotlin/src/main/kotlin/com/baeldung/klaxon/Product.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/Product.kt
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/klaxon/ProductData.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/ProductData.kt
similarity index 100%
rename from core-kotlin/src/main/kotlin/com/baeldung/klaxon/ProductData.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/ProductData.kt
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/Controller.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Controller.kt
similarity index 100%
rename from core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/Controller.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Controller.kt
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/Dao.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Dao.kt
similarity index 100%
rename from core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/Dao.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Dao.kt
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/JdbcDao.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/JdbcDao.kt
similarity index 100%
rename from core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/JdbcDao.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/JdbcDao.kt
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/MongoDao.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/MongoDao.kt
similarity index 100%
rename from core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/MongoDao.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/MongoDao.kt
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/Service.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Service.kt
similarity index 100%
rename from core-kotlin/src/main/kotlin/com/baeldung/kotlin/kodein/Service.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Service.kt
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/mockito/BookService.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/mockito/BookService.kt
similarity index 100%
rename from core-kotlin/src/main/kotlin/com/baeldung/kotlin/mockito/BookService.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/mockito/BookService.kt
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/mockito/LendBookManager.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/mockito/LendBookManager.kt
similarity index 100%
rename from core-kotlin/src/main/kotlin/com/baeldung/kotlin/mockito/LendBookManager.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/mockito/LendBookManager.kt
diff --git a/core-kotlin/kotlin-ktor/src/main/kotlin/APIServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/ktor/APIServer.kt
similarity index 100%
rename from core-kotlin/kotlin-ktor/src/main/kotlin/APIServer.kt
rename to kotlin-libraries/src/main/kotlin/com/baeldung/ktor/APIServer.kt
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/klaxon/KlaxonUnitTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/klaxon/KlaxonUnitTest.kt
similarity index 100%
rename from core-kotlin/src/test/kotlin/com/baeldung/klaxon/KlaxonUnitTest.kt
rename to kotlin-libraries/src/test/kotlin/com/baeldung/klaxon/KlaxonUnitTest.kt
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/exposed/ExposedTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/exposed/ExposedTest.kt
similarity index 100%
rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/exposed/ExposedTest.kt
rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/exposed/ExposedTest.kt
diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/Calculator.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/Calculator.kt
new file mode 100644
index 0000000000..1b61c05887
--- /dev/null
+++ b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/Calculator.kt
@@ -0,0 +1,17 @@
+package com.baeldung.kotlin.junit5
+
+class Calculator {
+ fun add(a: Int, b: Int) = a + b
+
+ fun divide(a: Int, b: Int) = if (b == 0) {
+ throw DivideByZeroException(a)
+ } else {
+ a / b
+ }
+
+ fun square(a: Int) = a * a
+
+ fun squareRoot(a: Int) = Math.sqrt(a.toDouble())
+
+ fun log(base: Int, value: Int) = Math.log(value.toDouble()) / Math.log(base.toDouble())
+}
diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/DivideByZeroException.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/DivideByZeroException.kt
new file mode 100644
index 0000000000..60bc4e2944
--- /dev/null
+++ b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/DivideByZeroException.kt
@@ -0,0 +1,3 @@
+package com.baeldung.kotlin.junit5
+
+class DivideByZeroException(val numerator: Int) : Exception()
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/khttp/KhttpLiveTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/khttp/KhttpLiveTest.kt
similarity index 100%
rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/khttp/KhttpLiveTest.kt
rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/khttp/KhttpLiveTest.kt
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/kodein/KodeinUnitTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/kodein/KodeinUnitTest.kt
similarity index 100%
rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/kodein/KodeinUnitTest.kt
rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/kodein/KodeinUnitTest.kt
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTest.kt
similarity index 100%
rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTest.kt
rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTest.kt
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTestMockitoKotlin.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTestMockitoKotlin.kt
similarity index 100%
rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTestMockitoKotlin.kt
rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTestMockitoKotlin.kt
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorSubjectTest5.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorSubjectTest5.kt
similarity index 100%
rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorSubjectTest5.kt
rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorSubjectTest5.kt
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorTest5.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorTest5.kt
similarity index 100%
rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorTest5.kt
rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorTest5.kt
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/spek/DataDrivenTest5.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/DataDrivenTest5.kt
similarity index 100%
rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/spek/DataDrivenTest5.kt
rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/DataDrivenTest5.kt
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/spek/GroupTest5.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/GroupTest5.kt
similarity index 100%
rename from core-kotlin/src/test/kotlin/com/baeldung/kotlin/spek/GroupTest5.kt
rename to kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/GroupTest5.kt
diff --git a/libraries/pom.xml b/libraries/pom.xml
index 4768268f59..f7980f10f6 100644
--- a/libraries/pom.xml
+++ b/libraries/pom.xml
@@ -777,19 +777,6 @@
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- org.apache.felix
- maven-bundle-plugin
- ${maven-bundle-plugin.version}
- maven-plugin
-
-
- true
-
maven-failsafe-plugin
${maven-failsafe-plugin.version}
@@ -946,7 +933,7 @@
2.5.5
1.23.0
v4-rev493-1.21.0
- 1.0.0
+ 2.0.0
1.7.0
3.0.14
2.2.0
diff --git a/libraries/src/main/java/com/baeldung/commons/lang3/application/Application.java b/libraries/src/main/java/com/baeldung/commons/lang3/application/Application.java
new file mode 100644
index 0000000000..7d4316e3ec
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/commons/lang3/application/Application.java
@@ -0,0 +1,8 @@
+package com.baeldung.commons.lang3.application;
+
+public class Application {
+
+ public static void main(String[] args) {
+
+ }
+}
diff --git a/libraries/src/main/java/com/baeldung/commons/lang3/beans/User.java b/libraries/src/main/java/com/baeldung/commons/lang3/beans/User.java
new file mode 100644
index 0000000000..68aab46c33
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/commons/lang3/beans/User.java
@@ -0,0 +1,25 @@
+package com.baeldung.commons.lang3.beans;
+
+public class User {
+
+ private final String name;
+ private final String email;
+
+ public User(String name, String email) {
+ this.name = name;
+ this.email = email;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ @Override
+ public String toString() {
+ return "User{" + "name=" + name + ", email=" + email + '}';
+ }
+}
diff --git a/libraries/src/main/java/com/baeldung/commons/lang3/beans/UserInitializer.java b/libraries/src/main/java/com/baeldung/commons/lang3/beans/UserInitializer.java
new file mode 100644
index 0000000000..ae5d80244c
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/commons/lang3/beans/UserInitializer.java
@@ -0,0 +1,11 @@
+package com.baeldung.commons.lang3.beans;
+
+import org.apache.commons.lang3.concurrent.LazyInitializer;
+
+public class UserInitializer extends LazyInitializer {
+
+ @Override
+ protected User initialize() {
+ return new User("John", "john@domain.com");
+ }
+}
diff --git a/libraries/src/main/java/com/baeldung/kafka/TransactionalApp.java b/libraries/src/main/java/com/baeldung/kafka/TransactionalApp.java
new file mode 100644
index 0000000000..1e95041a0d
--- /dev/null
+++ b/libraries/src/main/java/com/baeldung/kafka/TransactionalApp.java
@@ -0,0 +1,102 @@
+package com.baeldung.kafka;
+
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.apache.kafka.clients.consumer.ConsumerRecords;
+import org.apache.kafka.clients.consumer.KafkaConsumer;
+import org.apache.kafka.clients.consumer.OffsetAndMetadata;
+import org.apache.kafka.clients.producer.KafkaProducer;
+import org.apache.kafka.clients.producer.ProducerConfig;
+import org.apache.kafka.clients.producer.ProducerRecord;
+import org.apache.kafka.common.KafkaException;
+import org.apache.kafka.common.TopicPartition;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import static java.time.Duration.ofSeconds;
+import static java.util.Collections.singleton;
+import static org.apache.kafka.clients.consumer.ConsumerConfig.*;
+import static org.apache.kafka.clients.consumer.ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG;
+import static org.apache.kafka.clients.producer.ProducerConfig.*;
+
+public class TransactionalApp {
+
+ private static final String CONSUMER_GROUP_ID = "test";
+ private static final String OUTPUT_TOPIC = "output";
+ private static final String INPUT_TOPIC = "input";
+
+ public static void main(String[] args) {
+
+ KafkaConsumer consumer = initConsumer();
+ KafkaProducer producer = initProducer();
+
+ producer.initTransactions();
+
+ try {
+
+ while (true) {
+
+ ConsumerRecords records = consumer.poll(ofSeconds(20));
+
+ producer.beginTransaction();
+
+ for (ConsumerRecord record : records)
+ producer.send(new ProducerRecord(OUTPUT_TOPIC, record));
+
+ Map offsetsToCommit = new HashMap<>();
+
+ for (TopicPartition partition : records.partitions()) {
+ List> partitionedRecords = records.records(partition);
+ long offset = partitionedRecords.get(partitionedRecords.size() - 1).offset();
+
+ offsetsToCommit.put(partition, new OffsetAndMetadata(offset));
+ }
+
+ producer.sendOffsetsToTransaction(offsetsToCommit, CONSUMER_GROUP_ID);
+ producer.commitTransaction();
+
+ }
+
+ } catch (KafkaException e) {
+
+ producer.abortTransaction();
+
+ }
+
+
+ }
+
+ private static KafkaConsumer initConsumer() {
+ Properties props = new Properties();
+ props.put(BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
+ props.put(GROUP_ID_CONFIG, CONSUMER_GROUP_ID);
+ props.put(ENABLE_AUTO_COMMIT_CONFIG, "false");
+ props.put(KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
+ props.put(VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
+
+ KafkaConsumer consumer = new KafkaConsumer<>(props);
+ consumer.subscribe(singleton(INPUT_TOPIC));
+ return consumer;
+ }
+
+ private static KafkaProducer initProducer() {
+
+ Properties props = new Properties();
+ props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
+ props.put(ACKS_CONFIG, "all");
+ props.put(RETRIES_CONFIG, 3);
+ props.put(BATCH_SIZE_CONFIG, 16384);
+ props.put(LINGER_MS_CONFIG, 1);
+ props.put(BUFFER_MEMORY_CONFIG, 33554432);
+ props.put(ENABLE_IDEMPOTENCE_CONFIG, "true");
+ props.put(TRANSACTIONAL_ID_CONFIG, "prod-1");
+ props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
+ props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
+
+ return new KafkaProducer(props);
+
+ }
+
+}
diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/ArrayUtilsUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/ArrayUtilsUnitTest.java
new file mode 100644
index 0000000000..5eba736b4a
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/ArrayUtilsUnitTest.java
@@ -0,0 +1,84 @@
+package com.baeldung.commons.lang3.test;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.commons.lang3.ArrayUtils;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class ArrayUtilsUnitTest {
+
+ @Test
+ public void givenArrayUtilsClass_whenCalledtoString_thenCorrect() {
+ String[] array = {"a", "b", "c"};
+ assertThat(ArrayUtils.toString(array)).isEqualTo("{a,b,c}");
+ }
+
+ @Test
+ public void givenArrayUtilsClass_whenCalledtoStringIfArrayisNull_thenCorrect() {
+ String[] array = null;
+ assertThat(ArrayUtils.toString(array, "Array is null")).isEqualTo("Array is null");
+ }
+
+ @Test
+ public void givenArrayUtilsClass_whenCalledhashCode_thenCorrect() {
+ String[] array = {"a", "b", "c"};
+ assertThat(ArrayUtils.hashCode(array)).isEqualTo(997619);
+ }
+
+ @Test
+ public void givenArrayUtilsClass_whenCalledtoMap_thenCorrect() {
+ String[][] array = {{"1", "one", }, {"2", "two", }, {"3", "three"}};
+ Map map = new HashMap();
+ map.put("1", "one");
+ map.put("2", "two");
+ map.put("3", "three");
+ assertThat(ArrayUtils.toMap(array)).isEqualTo(map);
+ }
+
+ @Test
+ public void givenArrayUtilsClass_whenCallednullToEmptyStringArray_thenCorrect() {
+ String[] array = null;
+ assertThat(ArrayUtils.nullToEmpty(array)).isEmpty();
+ }
+
+ @Test
+ public void givenArrayUtilsClass_whenCallednullToEmptyObjectArray_thenCorrect() {
+ Object[] array = null;
+ assertThat(ArrayUtils.nullToEmpty(array)).isEmpty();
+ }
+
+ @Test
+ public void givenArrayUtilsClass_whenCalledsubarray_thenCorrect() {
+ int[] array = {1, 2, 3};
+ int[] expected = {1};
+ assertThat(ArrayUtils.subarray(array, 0, 1)).isEqualTo(expected);
+ }
+
+ @Test
+ public void givenArrayUtilsClass_whenCalledisSameLength_thenCorrect() {
+ int[] array1 = {1, 2, 3};
+ int[] array2 = {1, 2, 3};
+ assertThat(ArrayUtils.isSameLength(array1, array2)).isTrue();
+ }
+
+ @Test
+ public void givenArrayUtilsClass_whenCalledreverse_thenCorrect() {
+ int[] array1 = {1, 2, 3};
+ int[] array2 = {3, 2, 1};
+ ArrayUtils.reverse(array1);
+ assertThat(array1).isEqualTo(array2);
+ }
+
+ @Test
+ public void givenArrayUtilsClass_whenCalledIndexOf_thenCorrect() {
+ int[] array = {1, 2, 3};
+ assertThat(ArrayUtils.indexOf(array, 1, 0)).isEqualTo(0);
+ }
+
+ @Test
+ public void givenArrayUtilsClass_whenCalledcontains_thenCorrect() {
+ int[] array = {1, 2, 3};
+ assertThat(ArrayUtils.contains(array, 1)).isTrue();
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/BasicThreadFactoryUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/BasicThreadFactoryUnitTest.java
new file mode 100644
index 0000000000..f32980269a
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/BasicThreadFactoryUnitTest.java
@@ -0,0 +1,18 @@
+package com.baeldung.commons.lang3.test;
+
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class BasicThreadFactoryUnitTest {
+
+ @Test
+ public void givenBasicThreadFactoryInstance_whenCalledBuilder_thenCorrect() {
+ BasicThreadFactory factory = new BasicThreadFactory.Builder()
+ .namingPattern("workerthread-%d")
+ .daemon(true)
+ .priority(Thread.MAX_PRIORITY)
+ .build();
+ assertThat(factory).isInstanceOf(BasicThreadFactory.class);
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/ConstructorUtilsUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/ConstructorUtilsUnitTest.java
new file mode 100644
index 0000000000..f55f239d75
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/ConstructorUtilsUnitTest.java
@@ -0,0 +1,28 @@
+package com.baeldung.commons.lang3.test;
+
+import com.baeldung.commons.lang3.beans.User;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import org.apache.commons.lang3.reflect.ConstructorUtils;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class ConstructorUtilsUnitTest {
+
+ @Test
+ public void givenConstructorUtilsClass_whenCalledgetAccessibleConstructor_thenCorrect() {
+ assertThat(ConstructorUtils.getAccessibleConstructor(User.class, String.class, String.class)).isInstanceOf(Constructor.class);
+ }
+
+ @Test
+ public void givenConstructorUtilsClass_whenCalledinvokeConstructor_thenCorrect() throws Exception {
+ assertThat(ConstructorUtils.invokeConstructor(User.class, "name", "email")).isInstanceOf(User.class);
+ }
+
+ @Test
+ public void givenConstructorUtilsClass_whenCalledinvokeExactConstructor_thenCorrect() throws Exception {
+ String[] args = {"name", "email"};
+ Class[] parameterTypes= {String.class, String.class};
+ assertThat(ConstructorUtils.invokeExactConstructor(User.class, args, parameterTypes)).isInstanceOf(User.class);
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/FieldUtilsUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/FieldUtilsUnitTest.java
new file mode 100644
index 0000000000..8abb373e30
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/FieldUtilsUnitTest.java
@@ -0,0 +1,60 @@
+package com.baeldung.commons.lang3.test;
+
+import com.baeldung.commons.lang3.beans.User;
+import org.apache.commons.lang3.reflect.FieldUtils;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class FieldUtilsUnitTest {
+
+ private static User user;
+
+ @BeforeClass
+ public static void setUpUserInstance() {
+ user = new User("Julie", "julie@domain.com");
+ }
+
+ @Test
+ public void givenFieldUtilsClass_whenCalledgetField_thenCorrect() {
+ assertThat(FieldUtils.getField(User.class, "name", true).getName()).isEqualTo("name");
+ }
+
+ @Test
+ public void givenFieldUtilsClass_whenCalledgetFieldForceAccess_thenCorrect() {
+ assertThat(FieldUtils.getField(User.class, "name", true).getName()).isEqualTo("name");
+ }
+
+ @Test
+ public void givenFieldUtilsClass_whenCalledgetDeclaredFieldForceAccess_thenCorrect() {
+ assertThat(FieldUtils.getDeclaredField(User.class, "name", true).getName()).isEqualTo("name");
+ }
+
+ @Test
+ public void givenFieldUtilsClass_whenCalledgetAllField_thenCorrect() {
+ assertThat(FieldUtils.getAllFields(User.class).length).isEqualTo(2);
+ }
+
+ @Test
+ public void givenFieldUtilsClass_whenCalledreadField_thenCorrect() throws IllegalAccessException {
+ assertThat(FieldUtils.readField(user, "name", true)).isEqualTo("Julie");
+ }
+
+ @Test
+ public void givenFieldUtilsClass_whenCalledreadDeclaredField_thenCorrect() throws IllegalAccessException {
+ assertThat(FieldUtils.readDeclaredField(user, "name", true)).isEqualTo("Julie");
+ }
+
+ @Test
+ public void givenFieldUtilsClass_whenCalledwriteField_thenCorrect() throws IllegalAccessException {
+ FieldUtils.writeField(user, "name", "Julie", true);
+ assertThat(FieldUtils.readField(user, "name", true)).isEqualTo("Julie");
+
+ }
+
+ @Test
+ public void givenFieldUtilsClass_whenCalledwriteDeclaredField_thenCorrect() throws IllegalAccessException {
+ FieldUtils.writeDeclaredField(user, "name", "Julie", true);
+ assertThat(FieldUtils.readField(user, "name", true)).isEqualTo("Julie");
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/FractionUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/FractionUnitTest.java
new file mode 100644
index 0000000000..1a5094a16d
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/FractionUnitTest.java
@@ -0,0 +1,34 @@
+package com.baeldung.commons.lang3.test;
+
+import org.apache.commons.lang3.math.Fraction;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class FractionUnitTest {
+
+ @Test
+ public void givenFractionClass_whenCalledgetFraction_thenCorrect() {
+ assertThat(Fraction.getFraction(5, 6)).isInstanceOf(Fraction.class);
+ }
+
+ @Test
+ public void givenTwoFractionInstances_whenCalledadd_thenCorrect() {
+ Fraction fraction1 = Fraction.getFraction(1, 4);
+ Fraction fraction2 = Fraction.getFraction(3, 4);
+ assertThat(fraction1.add(fraction2).toString()).isEqualTo("1/1");
+ }
+
+ @Test
+ public void givenTwoFractionInstances_whenCalledsubstract_thenCorrect() {
+ Fraction fraction1 = Fraction.getFraction(3, 4);
+ Fraction fraction2 = Fraction.getFraction(1, 4);
+ assertThat(fraction1.subtract(fraction2).toString()).isEqualTo("1/2");
+ }
+
+ @Test
+ public void givenTwoFractionInstances_whenCalledmultiply_thenCorrect() {
+ Fraction fraction1 = Fraction.getFraction(3, 4);
+ Fraction fraction2 = Fraction.getFraction(1, 4);
+ assertThat(fraction1.multiplyBy(fraction2).toString()).isEqualTo("3/16");
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/HashCodeBuilderUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/HashCodeBuilderUnitTest.java
new file mode 100644
index 0000000000..bbd24c8207
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/HashCodeBuilderUnitTest.java
@@ -0,0 +1,17 @@
+package com.baeldung.commons.lang3.test;
+
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class HashCodeBuilderUnitTest {
+
+ @Test
+ public void givenHashCodeBuilderInstance_whenCalledtoHashCode_thenCorrect() {
+ int hashcode = new HashCodeBuilder(17, 37)
+ .append("John")
+ .append("john@domain.com")
+ .toHashCode();
+ assertThat(hashcode).isEqualTo(1269178828);
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/ImmutablePairUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/ImmutablePairUnitTest.java
new file mode 100644
index 0000000000..28ed8d2514
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/ImmutablePairUnitTest.java
@@ -0,0 +1,36 @@
+package com.baeldung.commons.lang3.test;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ImmutablePairUnitTest {
+
+ private static ImmutablePair immutablePair;
+
+ @BeforeClass
+ public static void setUpImmutablePairInstance() {
+ immutablePair = new ImmutablePair<>("leftElement", "rightElement");
+ }
+
+ @Test
+ public void givenImmutablePairInstance_whenCalledgetLeft_thenCorrect() {
+ assertThat(immutablePair.getLeft()).isEqualTo("leftElement");
+ }
+
+ @Test
+ public void givenImmutablePairInstance_whenCalledgetRight_thenCorrect() {
+ assertThat(immutablePair.getRight()).isEqualTo("rightElement");
+ }
+
+ @Test
+ public void givenImmutablePairInstance_whenCalledof_thenCorrect() {
+ assertThat(ImmutablePair.of("leftElement", "rightElement")).isInstanceOf(ImmutablePair.class);
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void givenImmutablePairInstance_whenCalledSetValue_thenThrowUnsupportedOperationException() {
+ immutablePair.setValue("newValue");
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/ImmutableTripleUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/ImmutableTripleUnitTest.java
new file mode 100644
index 0000000000..a9dd3fa7c0
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/ImmutableTripleUnitTest.java
@@ -0,0 +1,31 @@
+package com.baeldung.commons.lang3.test;
+
+import org.apache.commons.lang3.tuple.ImmutableTriple;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ImmutableTripleUnitTest {
+
+ private static ImmutableTriple immutableTriple;
+
+ @BeforeClass
+ public static void setUpImmutableTripleInstance() {
+ immutableTriple = new ImmutableTriple<>("leftElement", "middleElement", "rightElement");
+ }
+
+ @Test
+ public void givenImmutableTripleInstance_whenCalledgetLeft_thenCorrect() {
+ assertThat(immutableTriple.getLeft()).isEqualTo("leftElement");
+ }
+
+ @Test
+ public void givenImmutableTripleInstance_whenCalledgetMiddle_thenCorrect() {
+ assertThat(immutableTriple.getMiddle()).isEqualTo("middleElement");
+ }
+
+ @Test
+ public void givenImmutableInstance_whenCalledgetRight_thenCorrect() {
+ assertThat(immutableTriple.getRight()).isEqualTo("rightElement");
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/LazyInitializerUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/LazyInitializerUnitTest.java
new file mode 100644
index 0000000000..a08399f8de
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/LazyInitializerUnitTest.java
@@ -0,0 +1,16 @@
+package com.baeldung.commons.lang3.test;
+
+import com.baeldung.commons.lang3.beans.User;
+import com.baeldung.commons.lang3.beans.UserInitializer;
+import org.apache.commons.lang3.concurrent.ConcurrentException;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class LazyInitializerUnitTest {
+
+ @Test
+ public void givenLazyInitializerInstance_whenCalledget_thenCorrect() throws ConcurrentException {
+ UserInitializer userInitializer = new UserInitializer();
+ assertThat(userInitializer.get()).isInstanceOf(User.class);
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/MethodUtilsUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/MethodUtilsUnitTest.java
new file mode 100644
index 0000000000..5e1d15f2f8
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/MethodUtilsUnitTest.java
@@ -0,0 +1,15 @@
+package com.baeldung.commons.lang3.test;
+
+import com.baeldung.commons.lang3.beans.User;
+import java.lang.reflect.Method;
+import org.apache.commons.lang3.reflect.MethodUtils;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class MethodUtilsUnitTest {
+
+ @Test
+ public void givenMethodUtilsClass_whenCalledgetAccessibleMethod_thenCorrect() {
+ assertThat(MethodUtils.getAccessibleMethod(User.class, "getName")).isInstanceOf(Method.class);
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/MutableObjectUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/MutableObjectUnitTest.java
new file mode 100644
index 0000000000..02041f51e8
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/MutableObjectUnitTest.java
@@ -0,0 +1,32 @@
+package com.baeldung.commons.lang3.test;
+
+import org.apache.commons.lang3.mutable.MutableObject;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class MutableObjectUnitTest {
+
+ private static MutableObject mutableObject;
+
+ @BeforeClass
+ public static void setUpMutableObject() {
+ mutableObject = new MutableObject("Initial value");
+ }
+
+ @Test
+ public void givenMutableObject_whenCalledgetValue_thenCorrect() {
+ assertThat(mutableObject.getValue()).isInstanceOf(String.class);
+ }
+
+ @Test
+ public void givenMutableObject_whenCalledsetValue_thenCorrect() {
+ mutableObject.setValue("Another value");
+ assertThat(mutableObject.getValue()).isEqualTo("Another value");
+ }
+
+ @Test
+ public void givenMutableObject_whenCalledtoString_thenCorrect() {
+ assertThat(mutableObject.toString()).isEqualTo("Another value");
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/MutablePairUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/MutablePairUnitTest.java
new file mode 100644
index 0000000000..174ec70c4d
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/MutablePairUnitTest.java
@@ -0,0 +1,32 @@
+package com.baeldung.commons.lang3.test;
+
+import org.apache.commons.lang3.tuple.MutablePair;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class MutablePairUnitTest {
+
+ private static MutablePair mutablePair;
+
+ @BeforeClass
+ public static void setUpMutablePairInstance() {
+ mutablePair = new MutablePair<>("leftElement", "rightElement");
+ }
+
+ @Test
+ public void givenMutablePairInstance_whenCalledgetLeft_thenCorrect() {
+ assertThat(mutablePair.getLeft()).isEqualTo("leftElement");
+ }
+
+ @Test
+ public void givenMutablePairInstance_whenCalledgetRight_thenCorrect() {
+ assertThat(mutablePair.getRight()).isEqualTo("rightElement");
+ }
+
+ @Test
+ public void givenMutablePairInstance_whenCalledsetLeft_thenCorrect() {
+ mutablePair.setLeft("newLeftElement");
+ assertThat(mutablePair.getLeft()).isEqualTo("newLeftElement");
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/NumberUtilsUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/NumberUtilsUnitTest.java
new file mode 100644
index 0000000000..bdf254a102
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/NumberUtilsUnitTest.java
@@ -0,0 +1,46 @@
+package com.baeldung.commons.lang3.test;
+
+import org.apache.commons.lang3.math.NumberUtils;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class NumberUtilsUnitTest {
+
+ @Test
+ public void givenNumberUtilsClass_whenCalledcompareWithIntegers_thenCorrect() {
+ assertThat(NumberUtils.compare(1, 1)).isEqualTo(0);
+ }
+
+ @Test
+ public void givenNumberUtilsClass_whenCalledcompareWithLongs_thenCorrect() {
+ assertThat(NumberUtils.compare(1L, 1L)).isEqualTo(0);
+ }
+
+ @Test
+ public void givenNumberUtilsClass_whenCalledcreateNumber_thenCorrect() {
+ assertThat(NumberUtils.createNumber("123456")).isEqualTo(123456);
+ }
+
+ @Test
+ public void givenNumberUtilsClass_whenCalledisDigits_thenCorrect() {
+ assertThat(NumberUtils.isDigits("123456")).isTrue();
+ }
+
+ @Test
+ public void givenNumberUtilsClass_whenCallemaxwithIntegerArray_thenCorrect() {
+ int[] array = {1, 2, 3, 4, 5, 6};
+ assertThat(NumberUtils.max(array)).isEqualTo(6);
+ }
+
+ @Test
+ public void givenNumberUtilsClass_whenCalleminwithIntegerArray_thenCorrect() {
+ int[] array = {1, 2, 3, 4, 5, 6};
+ assertThat(NumberUtils.min(array)).isEqualTo(1);
+ }
+
+ @Test
+ public void givenNumberUtilsClass_whenCalleminwithByteArray_thenCorrect() {
+ byte[] array = {1, 2, 3, 4, 5, 6};
+ assertThat(NumberUtils.min(array)).isEqualTo((byte) 1);
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/StringUtilsUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/StringUtilsUnitTest.java
new file mode 100644
index 0000000000..ab39ba7bd9
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/StringUtilsUnitTest.java
@@ -0,0 +1,73 @@
+package com.baeldung.commons.lang3.test;
+
+import org.apache.commons.lang3.StringUtils;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class StringUtilsUnitTest {
+
+ @Test
+ public void givenStringUtilsClass_whenCalledisBlank_thenCorrect() {
+ assertThat(StringUtils.isBlank(" ")).isTrue();
+ }
+
+ @Test
+ public void givenStringUtilsClass_whenCalledisEmpty_thenCorrect() {
+ assertThat(StringUtils.isEmpty("")).isTrue();
+ }
+
+ @Test
+ public void givenStringUtilsClass_whenCalledisAllLowerCase_thenCorrect() {
+ assertThat(StringUtils.isAllLowerCase("abd")).isTrue();
+ }
+
+ @Test
+ public void givenStringUtilsClass_whenCalledisAllUpperCase_thenCorrect() {
+ assertThat(StringUtils.isAllUpperCase("ABC")).isTrue();
+ }
+
+ @Test
+ public void givenStringUtilsClass_whenCalledisMixedCase_thenCorrect() {
+ assertThat(StringUtils.isMixedCase("abC")).isTrue();
+ }
+
+ @Test
+ public void givenStringUtilsClass_whenCalledisAlpha_thenCorrect() {
+ assertThat(StringUtils.isAlpha("abc")).isTrue();
+ }
+
+ @Test
+ public void givenStringUtilsClass_whenCalledisAlphanumeric_thenCorrect() {
+ assertThat(StringUtils.isAlphanumeric("abc123")).isTrue();
+ }
+
+ @Test
+ public void givenStringUtilsClass_whenCalledcontains_thenCorrect() {
+ assertThat(StringUtils.contains("abc", "ab")).isTrue();
+ }
+
+ @Test
+ public void givenStringUtilsClass_whenCalledcontainsAny_thenCorrect() {
+ assertThat(StringUtils.containsAny("abc", 'a', 'b', 'c')).isTrue();
+ }
+
+ @Test
+ public void givenStringUtilsClass_whenCalledcontainsIgnoreCase_thenCorrect() {
+ assertThat(StringUtils.containsIgnoreCase("abc", "ABC")).isTrue();
+ }
+
+ @Test
+ public void givenStringUtilsClass_whenCalledswapCase_thenCorrect() {
+ assertThat(StringUtils.swapCase("abc")).isEqualTo("ABC");
+ }
+
+ @Test
+ public void givenStringUtilsClass_whenCalledreverse_thenCorrect() {
+ assertThat(StringUtils.reverse("abc")).isEqualTo("cba");
+ }
+
+ @Test
+ public void givenStringUtilsClass_whenCalleddifference_thenCorrect() {
+ assertThat(StringUtils.difference("abc", "abd")).isEqualTo("d");
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/SystemsUtilsUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/SystemsUtilsUnitTest.java
new file mode 100644
index 0000000000..0efe97f912
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/SystemsUtilsUnitTest.java
@@ -0,0 +1,25 @@
+package com.baeldung.commons.lang3.test;
+
+import java.io.File;
+import org.apache.commons.lang3.JavaVersion;
+import org.apache.commons.lang3.SystemUtils;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class SystemsUtilsUnitTest {
+
+ @Test
+ public void givenSystemUtilsClass_whenCalledgetJavaHome_thenCorrect() {
+ assertThat(SystemUtils.getJavaHome()).isEqualTo(new File("/usr/lib/jvm/java-8-oracle/jre"));
+ }
+
+ @Test
+ public void givenSystemUtilsClass_whenCalledgetUserHome_thenCorrect() {
+ assertThat(SystemUtils.getUserHome()).isEqualTo(new File("/home/travis"));
+ }
+
+ @Test
+ public void givenSystemUtilsClass_whenCalledisJavaVersionAtLeast_thenCorrect() {
+ assertThat(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_RECENT)).isTrue();
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/commons/lang3/test/TripleUnitTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/test/TripleUnitTest.java
new file mode 100644
index 0000000000..7d506bbbab
--- /dev/null
+++ b/libraries/src/test/java/com/baeldung/commons/lang3/test/TripleUnitTest.java
@@ -0,0 +1,31 @@
+package com.baeldung.commons.lang3.test;
+
+import org.apache.commons.lang3.tuple.Triple;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TripleUnitTest {
+
+ private static Triple triple;
+
+ @BeforeClass
+ public static void setUpTripleInstance() {
+ triple = Triple.of("leftElement", "middleElement", "rightElement");
+ }
+
+ @Test
+ public void givenTripleInstance_whenCalledgetLeft_thenCorrect() {
+ assertThat(triple.getLeft()).isEqualTo("leftElement");
+ }
+
+ @Test
+ public void givenTripleInstance_whenCalledgetMiddle_thenCorrect() {
+ assertThat(triple.getMiddle()).isEqualTo("middleElement");
+ }
+
+ @Test
+ public void givenTripleInstance_whenCalledgetRight_thenCorrect() {
+ assertThat(triple.getRight()).isEqualTo("rightElement");
+ }
+}
diff --git a/libraries/src/test/java/com/baeldung/kafkastreams/KafkaStreamsLiveTest.java b/libraries/src/test/java/com/baeldung/kafkastreams/KafkaStreamsLiveTest.java
index 4406494d30..e61f4158a7 100644
--- a/libraries/src/test/java/com/baeldung/kafkastreams/KafkaStreamsLiveTest.java
+++ b/libraries/src/test/java/com/baeldung/kafkastreams/KafkaStreamsLiveTest.java
@@ -4,10 +4,12 @@ import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.Serde;
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KafkaStreams;
+import org.apache.kafka.streams.StreamsBuilder;
import org.apache.kafka.streams.StreamsConfig;
+import org.apache.kafka.streams.Topology;
import org.apache.kafka.streams.kstream.KStream;
-import org.apache.kafka.streams.kstream.KStreamBuilder;
import org.apache.kafka.streams.kstream.KTable;
+import org.apache.kafka.streams.kstream.Produced;
import org.apache.kafka.test.TestUtils;
import org.junit.Ignore;
import org.junit.Test;
@@ -36,20 +38,20 @@ public class KafkaStreamsLiveTest {
streamsConfiguration.put(StreamsConfig.STATE_DIR_CONFIG, TestUtils.tempDirectory().getAbsolutePath());
// when
- KStreamBuilder builder = new KStreamBuilder();
+ StreamsBuilder builder = new StreamsBuilder();
KStream textLines = builder.stream(inputTopic);
Pattern pattern = Pattern.compile("\\W+", Pattern.UNICODE_CHARACTER_CLASS);
KTable wordCounts = textLines.flatMapValues(value -> Arrays.asList(pattern.split(value.toLowerCase()))).groupBy((key, word) -> word).count();
- wordCounts.foreach((word, count) -> System.out.println("word: " + word + " -> " + count));
+ textLines.foreach((word, count) -> System.out.println("word: " + word + " -> " + count));
String outputTopic = "outputTopic";
final Serde stringSerde = Serdes.String();
- final Serde longSerde = Serdes.Long();
- wordCounts.to(stringSerde, longSerde, outputTopic);
+ final Serde longSerde = Serdes.String();
+ textLines.to(outputTopic, Produced.with(stringSerde,longSerde));
- KafkaStreams streams = new KafkaStreams(builder, streamsConfiguration);
+ KafkaStreams streams = new KafkaStreams(new Topology(), streamsConfiguration);
streams.start();
// then
diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/Child.java b/lombok/src/main/java/com/baeldung/lombok/builder/Child.java
new file mode 100644
index 0000000000..70f6d9c46e
--- /dev/null
+++ b/lombok/src/main/java/com/baeldung/lombok/builder/Child.java
@@ -0,0 +1,19 @@
+package com.baeldung.lombok.builder;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Getter
+public class Child extends Parent {
+
+ private final String childName;
+ private final int childAge;
+
+ @Builder(builderMethodName = "childBuilder")
+ public Child(String parentName, int parentAge, String childName, int childAge) {
+ super(parentName, parentAge);
+ this.childName = childName;
+ this.childAge = childAge;
+ }
+
+}
diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/Parent.java b/lombok/src/main/java/com/baeldung/lombok/builder/Parent.java
new file mode 100644
index 0000000000..0cf76d4b00
--- /dev/null
+++ b/lombok/src/main/java/com/baeldung/lombok/builder/Parent.java
@@ -0,0 +1,11 @@
+package com.baeldung.lombok.builder;
+
+import lombok.Builder;
+import lombok.Getter;
+
+@Getter
+@Builder
+public class Parent {
+ private final String parentName;
+ private final int parentAge;
+}
\ No newline at end of file
diff --git a/lombok/src/main/java/com/baeldung/lombok/getter/GetterBoolean.java b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBoolean.java
new file mode 100644
index 0000000000..2191396e5d
--- /dev/null
+++ b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBoolean.java
@@ -0,0 +1,15 @@
+package com.baeldung.lombok.getter;
+
+
+import lombok.Getter;
+
+/**
+ * Related Article Sections:
+ * 4. Using @Getter on a Boolean Field
+ *
+ */
+public class GetterBoolean {
+
+ @Getter
+ private Boolean running = true;
+}
diff --git a/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanPrimitive.java b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanPrimitive.java
new file mode 100644
index 0000000000..5601f85b8b
--- /dev/null
+++ b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanPrimitive.java
@@ -0,0 +1,16 @@
+package com.baeldung.lombok.getter;
+
+
+import lombok.Getter;
+
+/**
+ * Related Article Sections:
+ * 3. Using @Getter on a boolean Field
+ *
+ */
+public class GetterBooleanPrimitive {
+
+ @Getter
+ private boolean running;
+
+}
diff --git a/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanPrimitiveSameAccessor.java b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanPrimitiveSameAccessor.java
new file mode 100644
index 0000000000..af29a33c20
--- /dev/null
+++ b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanPrimitiveSameAccessor.java
@@ -0,0 +1,18 @@
+package com.baeldung.lombok.getter;
+
+
+import lombok.Getter;
+
+/**
+ * Related Article Sections:
+ * 3.2. Two boolean Fields With the Same Accessor Name
+ *
+ */
+public class GetterBooleanPrimitiveSameAccessor {
+
+ @Getter
+ boolean running = true;
+
+ @Getter
+ boolean isRunning = false;
+}
diff --git a/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanSameAccessor.java b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanSameAccessor.java
new file mode 100644
index 0000000000..d972273b71
--- /dev/null
+++ b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanSameAccessor.java
@@ -0,0 +1,13 @@
+package com.baeldung.lombok.getter;
+
+import lombok.Getter;
+
+/**
+ * Related Article Sections:
+ * 3.1. A boolean Field Having the Same Name With Its Accessor
+ *
+ */
+public class GetterBooleanSameAccessor {
+ @Getter
+ private boolean isRunning = true;
+}
diff --git a/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanType.java b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanType.java
new file mode 100644
index 0000000000..0d3b9a928a
--- /dev/null
+++ b/lombok/src/main/java/com/baeldung/lombok/getter/GetterBooleanType.java
@@ -0,0 +1,15 @@
+package com.baeldung.lombok.getter;
+
+
+import lombok.Getter;
+
+/**
+ * Related Article Sections:
+ * 4. Using @Getter on a Boolean Field
+ *
+ */
+public class GetterBooleanType {
+
+ @Getter
+ private Boolean running = true;
+}
diff --git a/lombok/src/test/java/com/baeldung/lombok/builder/BuilderUnitTest.java b/lombok/src/test/java/com/baeldung/lombok/builder/BuilderUnitTest.java
index acad7d6c04..56a380569d 100644
--- a/lombok/src/test/java/com/baeldung/lombok/builder/BuilderUnitTest.java
+++ b/lombok/src/test/java/com/baeldung/lombok/builder/BuilderUnitTest.java
@@ -1,42 +1,59 @@
package com.baeldung.lombok.builder;
+import static org.assertj.core.api.Assertions.assertThat;
+
import org.junit.jupiter.api.Test;
-import static org.assertj.core.api.Assertions.*;
-
-public class BuilderUnitTest
-{
+public class BuilderUnitTest {
@Test
public void givenBuilder_WidgetIsBuilt() {
- Widget testWidget = Widget.builder().name("foo").id(1).build();
- assertThat(testWidget.getName())
- .isEqualTo("foo");
- assertThat(testWidget.getId())
- .isEqualTo(1);
+ Widget testWidget = Widget.builder()
+ .name("foo")
+ .id(1)
+ .build();
+ assertThat(testWidget.getName()).isEqualTo("foo");
+ assertThat(testWidget.getId()).isEqualTo(1);
}
@Test
public void givenToBuilder_whenToBuilder_BuilderIsCreated() {
- Widget testWidget = Widget.builder().name("foo").id(1).build();
+ Widget testWidget = Widget.builder()
+ .name("foo")
+ .id(1)
+ .build();
Widget.WidgetBuilder widgetBuilder = testWidget.toBuilder();
- Widget newWidget = widgetBuilder.id(2).build();
- assertThat(newWidget.getName())
- .isEqualTo("foo");
- assertThat(newWidget.getId())
- .isEqualTo(2);
+ Widget newWidget = widgetBuilder.id(2)
+ .build();
+ assertThat(newWidget.getName()).isEqualTo("foo");
+ assertThat(newWidget.getId()).isEqualTo(2);
}
-
-
@Test
public void givenBuilderMethod_ClientIsBuilt() {
- ImmutableClient testImmutableClient = ClientBuilder.builder().name("foo").id(1).build();
- assertThat(testImmutableClient.getName())
- .isEqualTo("foo");
- assertThat(testImmutableClient.getId())
- .isEqualTo(1);
+ ImmutableClient testImmutableClient = ClientBuilder.builder()
+ .name("foo")
+ .id(1)
+ .build();
+ assertThat(testImmutableClient.getName()).isEqualTo("foo");
+ assertThat(testImmutableClient.getId()).isEqualTo(1);
}
+
+ @Test
+ public void givenBuilderAtMethodLevel_ChildInheritingParentIsBuilt() {
+ Child child = Child.childBuilder()
+ .parentName("Andrea")
+ .parentAge(38)
+ .childName("Emma")
+ .childAge(6)
+ .build();
+
+ assertThat(child.getChildName()).isEqualTo("Emma");
+ assertThat(child.getChildAge()).isEqualTo(6);
+ assertThat(child.getParentName()).isEqualTo("Andrea");
+ assertThat(child.getParentAge()).isEqualTo(38);
+ }
+
}
diff --git a/lombok/src/test/java/com/baeldung/lombok/getter/GetterBooleanUnitTest.java b/lombok/src/test/java/com/baeldung/lombok/getter/GetterBooleanUnitTest.java
new file mode 100644
index 0000000000..632594d575
--- /dev/null
+++ b/lombok/src/test/java/com/baeldung/lombok/getter/GetterBooleanUnitTest.java
@@ -0,0 +1,34 @@
+package com.baeldung.lombok.getter;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class GetterBooleanUnitTest {
+
+ @Test
+ public void whenBasicBooleanField_thenMethodNamePrefixedWithIsFollowedByFieldName() {
+ GetterBooleanPrimitive lombokExamples = new GetterBooleanPrimitive();
+ assertFalse(lombokExamples.isRunning());
+ }
+
+ @Test
+ public void whenBooleanFieldPrefixedWithIs_thenMethodNameIsSameAsFieldName() {
+ GetterBooleanSameAccessor lombokExamples = new GetterBooleanSameAccessor();
+ assertTrue(lombokExamples.isRunning());
+ }
+
+ @Test
+ public void whenTwoBooleanFieldsCauseNamingConflict_thenLombokMapsToFirstDeclaredField() {
+ GetterBooleanPrimitiveSameAccessor lombokExamples = new GetterBooleanPrimitiveSameAccessor();
+ assertTrue(lombokExamples.isRunning() == lombokExamples.running);
+ assertFalse(lombokExamples.isRunning() == lombokExamples.isRunning);
+ }
+
+ @Test
+ public void whenFieldOfBooleanType_thenLombokPrefixesMethodWithGetInsteadOfIs() {
+ GetterBooleanType lombokExamples = new GetterBooleanType();
+ assertTrue(lombokExamples.getRunning());
+ }
+}
diff --git a/metrics/pom.xml b/metrics/pom.xml
index 86f197240b..9cf1ec588f 100644
--- a/metrics/pom.xml
+++ b/metrics/pom.xml
@@ -84,6 +84,13 @@
spectator-api
${spectator-api.version}
+
+
+ org.assertj
+ assertj-core
+ test
+
+
diff --git a/metrics/src/test/java/com/baeldung/metrics/micrometer/MicrometerAtlasIntegrationTest.java b/metrics/src/test/java/com/baeldung/metrics/micrometer/MicrometerAtlasIntegrationTest.java
index e7f3d7ec72..689e23ad6d 100644
--- a/metrics/src/test/java/com/baeldung/metrics/micrometer/MicrometerAtlasIntegrationTest.java
+++ b/metrics/src/test/java/com/baeldung/metrics/micrometer/MicrometerAtlasIntegrationTest.java
@@ -1,8 +1,12 @@
package com.baeldung.metrics.micrometer;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.within;
+import static org.assertj.core.api.Assertions.withinPercentage;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.collection.IsMapContaining.hasEntry;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import io.micrometer.atlas.AtlasMeterRegistry;
@@ -31,8 +35,10 @@ import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
+import org.assertj.core.data.Percentage;
import org.junit.Before;
import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
import com.netflix.spectator.atlas.AtlasConfig;
@@ -156,7 +162,8 @@ public class MicrometerAtlasIntegrationTest {
timer.record(30, TimeUnit.MILLISECONDS);
assertTrue(2 == timer.count());
- assertTrue(50 > timer.totalTime(TimeUnit.MILLISECONDS) && 45 <= timer.totalTime(TimeUnit.MILLISECONDS));
+
+ assertThat(timer.totalTime(TimeUnit.MILLISECONDS)).isBetween(40.0, 55.0);
}
@Test
@@ -173,7 +180,7 @@ public class MicrometerAtlasIntegrationTest {
}
long timeElapsed = longTaskTimer.stop(currentTaskId);
- assertTrue(timeElapsed / (int) 1e6 == 2);
+ assertEquals(2L, timeElapsed/((int) 1e6),1L);
}
@Test
diff --git a/metrics/src/test/java/com/baeldung/metrics/servo/AtlasObserverLiveTest.java b/metrics/src/test/java/com/baeldung/metrics/servo/AtlasObserverLiveTest.java
index 134c3c91cf..b8a5b93e49 100644
--- a/metrics/src/test/java/com/baeldung/metrics/servo/AtlasObserverLiveTest.java
+++ b/metrics/src/test/java/com/baeldung/metrics/servo/AtlasObserverLiveTest.java
@@ -27,6 +27,9 @@ import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
+/**
+ * Atlas server needs to be up and running for this live test to work.
+ */
public class AtlasObserverLiveTest {
private final String atlasUri = "http://localhost:7101/api/v1";
diff --git a/metrics/src/test/java/com/baeldung/metrics/servo/MetricTypeManualTest.java b/metrics/src/test/java/com/baeldung/metrics/servo/MetricTypeManualTest.java
index d810de155a..92bbd615b9 100644
--- a/metrics/src/test/java/com/baeldung/metrics/servo/MetricTypeManualTest.java
+++ b/metrics/src/test/java/com/baeldung/metrics/servo/MetricTypeManualTest.java
@@ -109,20 +109,20 @@ public class MetricTypeManualTest {
.build(), MILLISECONDS);
Stopwatch stopwatch = timer.start();
- MILLISECONDS.sleep(1);
- timer.record(2, MILLISECONDS);
+ SECONDS.sleep(1);
+ timer.record(2, SECONDS);
stopwatch.stop();
- assertEquals("timer should count 1 millisecond", 1, timer
+ assertEquals("timer should count 1 second", 1000, timer
.getValue()
- .intValue());
- assertEquals("timer should count 3 millisecond in total", 3, timer.getTotalTime()
- .intValue());
+ .intValue(),1000);
+ assertEquals("timer should count 3 second in total", 3000, timer.getTotalTime()
+ .intValue(),1000);
assertEquals("timer should record 2 updates", 2, timer
.getCount()
.intValue());
- assertEquals("timer should have max 2", 2, timer.getMax(), 0.01);
+ assertEquals("timer should have max 2", 2000, timer.getMax(), 0.01);
}
@Test
@@ -161,7 +161,6 @@ public class MetricTypeManualTest {
}
@Test
- //==
public void givenStatsTimer_whenExecuteTask_thenStatsCalculated() throws Exception {
System.setProperty("netflix.servo", "1000");
StatsTimer timer = new StatsTimer(MonitorConfig
@@ -178,21 +177,21 @@ public class MetricTypeManualTest {
.build(), MILLISECONDS);
Stopwatch stopwatch = timer.start();
- MILLISECONDS.sleep(1);
- timer.record(3, MILLISECONDS);
+ SECONDS.sleep(1);
+ timer.record(3, SECONDS);
stopwatch.stop();
stopwatch = timer.start();
- timer.record(6, MILLISECONDS);
- MILLISECONDS.sleep(2);
+ timer.record(6, SECONDS);
+ SECONDS.sleep(2);
stopwatch.stop();
- assertEquals("timer should count 12 milliseconds in total", 12, timer.getTotalTime());
- assertEquals("timer should count 12 milliseconds in total", 12, timer.getTotalMeasurement());
+ assertEquals("timer should count 12 seconds in total", 12000, timer.getTotalTime(),500);
+ assertEquals("timer should count 12 seconds in total", 12000, timer.getTotalMeasurement(),500);
assertEquals("timer should record 4 updates", 4, timer.getCount());
- assertEquals("stats timer value time-cost/update should be 2", 3, timer
+ assertEquals("stats timer value time-cost/update should be 2", 3000, timer
.getValue()
- .intValue());
+ .intValue(),500);
final Map metricMap = timer
.getMonitors()
@@ -235,4 +234,4 @@ public class MetricTypeManualTest {
assertEquals("information collected", informational.getValue());
}
-}
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-data-dynamodb/pom.xml b/persistence-modules/spring-data-dynamodb/pom.xml
index f3d794d001..4cb805131a 100644
--- a/persistence-modules/spring-data-dynamodb/pom.xml
+++ b/persistence-modules/spring-data-dynamodb/pom.xml
@@ -154,25 +154,6 @@
org.apache.maven.plugins
maven-war-plugin
-
- org.apache.maven.plugins
- maven-dependency-plugin
- ${maven-dependency-plugin.version}
-
-
- copy-dependencies
- test-compile
-
- copy-dependencies
-
-
- test
- so,dll,dylib
- ${project.basedir}/native-libs
-
-
-
-
@@ -196,7 +177,6 @@
1.11.106
1.11.86
https://s3-us-west-2.amazonaws.com/dynamodb-local/release
- 2.10
diff --git a/pom.xml b/pom.xml
index b10cab6b1a..7a7e2d7f64 100644
--- a/pom.xml
+++ b/pom.xml
@@ -352,6 +352,7 @@
java-streams
core-java-persistence
core-kotlin
+ kotlin-libraries
core-groovy
core-java-concurrency
core-java-concurrency-collections
@@ -602,6 +603,7 @@
spring-reactive-kotlin
jnosql
spring-boot-angular-ecommerce
+ jta
@@ -961,6 +963,7 @@
json-path
json
jsoup
+ jta
testing-modules/junit-5
testing-modules/junit5-migration
jws
@@ -1238,6 +1241,7 @@
spring-boot-ops
spring-5
core-kotlin
+ kotlin-libraries
core-java
google-web-toolkit
spring-security-mvc-custom
@@ -1309,4 +1313,4 @@
3.8
-
\ No newline at end of file
+
diff --git a/spring-all/pom.xml b/spring-all/pom.xml
index c4c4cf7963..6e765d5a9e 100644
--- a/spring-all/pom.xml
+++ b/spring-all/pom.xml
@@ -190,7 +190,24 @@
-
+
+
+ dev
+
+ true
+
+
+ dev
+
+
+
+ prod
+
+ prod
+
+
+
+
org.baeldung.sample.App
diff --git a/spring-all/src/main/java/org/baeldung/profiles/SpringProfilesConfig.java b/spring-all/src/main/java/org/baeldung/profiles/SpringProfilesConfig.java
index eb5543e3db..2d1905ee9c 100644
--- a/spring-all/src/main/java/org/baeldung/profiles/SpringProfilesConfig.java
+++ b/spring-all/src/main/java/org/baeldung/profiles/SpringProfilesConfig.java
@@ -2,9 +2,11 @@ package org.baeldung.profiles;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
@Configuration
@ComponentScan("org.baeldung.profiles")
+@PropertySource(value = "classpath:application.properties")
public class SpringProfilesConfig {
}
diff --git a/spring-all/src/main/resources/application.properties b/spring-all/src/main/resources/application.properties
new file mode 100644
index 0000000000..cbfe3f2df2
--- /dev/null
+++ b/spring-all/src/main/resources/application.properties
@@ -0,0 +1 @@
+spring.profiles.active=@spring.profiles.active@
\ No newline at end of file
diff --git a/spring-all/src/test/java/org/baeldung/profiles/SpringProfilesWithMavenPropertiesIntegrationTest.java b/spring-all/src/test/java/org/baeldung/profiles/SpringProfilesWithMavenPropertiesIntegrationTest.java
new file mode 100644
index 0000000000..929d088a14
--- /dev/null
+++ b/spring-all/src/test/java/org/baeldung/profiles/SpringProfilesWithMavenPropertiesIntegrationTest.java
@@ -0,0 +1,22 @@
+package org.baeldung.profiles;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { SpringProfilesConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class SpringProfilesWithMavenPropertiesIntegrationTest {
+
+ @Autowired
+ DatasourceConfig datasourceConfig;
+
+ @Test
+ public void testSpringProfiles() {
+ Assert.assertTrue(datasourceConfig instanceof DevDatasourceConfig);
+ }
+}
\ No newline at end of file
diff --git a/spring-boot-logging-log4j2/README.md b/spring-boot-logging-log4j2/README.md
index 7676bd1919..305957ed8d 100644
--- a/spring-boot-logging-log4j2/README.md
+++ b/spring-boot-logging-log4j2/README.md
@@ -1,2 +1,3 @@
### Relevant Articles:
- [Logging in Spring Boot](http://www.baeldung.com/spring-boot-logging)
+- [How to Disable Console Logging in Spring Boot](https://www.baeldung.com/spring-boot-disable-console-logging)
diff --git a/spring-boot-mvc/README.md b/spring-boot-mvc/README.md
index a22a6df667..b46dbe3bae 100644
--- a/spring-boot-mvc/README.md
+++ b/spring-boot-mvc/README.md
@@ -2,3 +2,9 @@
- [Guide to the Favicon in Spring Boot](http://www.baeldung.com/spring-boot-favicon)
- [Custom Validation MessageSource in Spring Boot](https://www.baeldung.com/spring-custom-validation-message-source)
+- [Spring Boot Annotations](http://www.baeldung.com/spring-boot-annotations)
+- [Spring Scheduling Annotations](http://www.baeldung.com/spring-scheduling-annotations)
+- [Spring Web Annotations](http://www.baeldung.com/spring-mvc-annotations)
+- [Spring Core Annotations](http://www.baeldung.com/spring-core-annotations)
+- [Display RSS Feed with Spring MVC](http://www.baeldung.com/spring-mvc-rss-feed)
+
diff --git a/spring-boot-mvc/pom.xml b/spring-boot-mvc/pom.xml
index d0fce26bb5..e456155f36 100644
--- a/spring-boot-mvc/pom.xml
+++ b/spring-boot-mvc/pom.xml
@@ -32,6 +32,13 @@
org.springframework.boot
spring-boot-starter-validation
+
+
+
+ com.rometools
+ rome
+ ${rome.version}
+
@@ -47,6 +54,8 @@
UTF-8
UTF-8
1.8
+
+ 1.10.0
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/Bike.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/Bike.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/Bike.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/Bike.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/Biker.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/Biker.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/Biker.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/Biker.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/Car.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/Car.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/Car.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/Car.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/CarMechanic.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/CarMechanic.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/CarMechanic.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/CarMechanic.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/CarUtility.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/CarUtility.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/CarUtility.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/CarUtility.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/CustomException.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/CustomException.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/CustomException.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/CustomException.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/CustomResponseController.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/CustomResponseController.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/CustomResponseController.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/CustomResponseController.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/CustomResponseWithBuilderController.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/CustomResponseWithBuilderController.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/CustomResponseWithBuilderController.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/CustomResponseWithBuilderController.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/Driver.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/Driver.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/Driver.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/Driver.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/Engine.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/Engine.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/Engine.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/Engine.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/Vehicle.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/Vehicle.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/Vehicle.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/Vehicle.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleController.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleController.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleController.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleController.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleFactoryApplication.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleFactoryApplication.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleFactoryApplication.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleFactoryApplication.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleFactoryConfig.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleFactoryConfig.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleFactoryConfig.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleFactoryConfig.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleRepository.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleRepository.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleRepository.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleRepository.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleRestController.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleRestController.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleRestController.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleRestController.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleService.java b/spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleService.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/annotations/VehicleService.java
rename to spring-boot-mvc/src/main/java/com/baeldung/annotations/VehicleService.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/rss/RssFeedApplication.java b/spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedApplication.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/rss/RssFeedApplication.java
rename to spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedApplication.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/rss/RssFeedController.java b/spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedController.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/rss/RssFeedController.java
rename to spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedController.java
diff --git a/spring-mvc-java/src/main/java/com/baeldung/rss/RssFeedView.java b/spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedView.java
similarity index 100%
rename from spring-mvc-java/src/main/java/com/baeldung/rss/RssFeedView.java
rename to spring-boot-mvc/src/main/java/com/baeldung/rss/RssFeedView.java
diff --git a/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/BeanA.java b/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/BeanA.java
new file mode 100644
index 0000000000..21d7007917
--- /dev/null
+++ b/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/BeanA.java
@@ -0,0 +1,12 @@
+package com.baeldung.springbootmvc.nosuchbeandefinitionexception;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class BeanA {
+
+ @Autowired
+ BeanB dependency;
+
+}
\ No newline at end of file
diff --git a/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/BeanB.java b/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/BeanB.java
new file mode 100644
index 0000000000..3dd72aacc6
--- /dev/null
+++ b/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/BeanB.java
@@ -0,0 +1,5 @@
+package com.baeldung.springbootmvc.nosuchbeandefinitionexception;
+
+public class BeanB {
+
+}
diff --git a/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/NoSuchBeanDefinitionDemoApp.java b/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/NoSuchBeanDefinitionDemoApp.java
new file mode 100644
index 0000000000..01d19437c5
--- /dev/null
+++ b/spring-boot-mvc/src/main/java/com/baeldung/springbootmvc/nosuchbeandefinitionexception/NoSuchBeanDefinitionDemoApp.java
@@ -0,0 +1,12 @@
+package com.baeldung.springbootmvc.nosuchbeandefinitionexception;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class NoSuchBeanDefinitionDemoApp {
+
+ public static void main(String[] args) {
+ SpringApplication.run(NoSuchBeanDefinitionDemoApp.class, args);
+ }
+}
diff --git a/spring-mvc-java/src/test/java/com/baeldung/rss/RssFeedUnitTest.java b/spring-boot-mvc/src/test/java/com/baeldung/rss/RssFeedUnitTest.java
similarity index 100%
rename from spring-mvc-java/src/test/java/com/baeldung/rss/RssFeedUnitTest.java
rename to spring-boot-mvc/src/test/java/com/baeldung/rss/RssFeedUnitTest.java
diff --git a/spring-boot-persistence/README.MD b/spring-boot-persistence/README.MD
index 72fdca74fa..6cf172426a 100644
--- a/spring-boot-persistence/README.MD
+++ b/spring-boot-persistence/README.MD
@@ -3,3 +3,4 @@
- [Spring Boot with Multiple SQL Import Files](http://www.baeldung.com/spring-boot-sql-import-files)
- [Configuring Separate Spring DataSource for Tests](http://www.baeldung.com/spring-testing-separate-data-source)
- [Quick Guide on data.sql and schema.sql Files in Spring Boot](http://www.baeldung.com/spring-boot-data-sql-and-schema-sql)
+- [Configuring a Tomcat Connection Pool in Spring Boot](https://www.baeldung.com/spring-boot-tomcat-connection-pool)
diff --git a/spring-boot/src/main/java/com/baeldung/properties/ConfigProperties.java b/spring-boot/src/main/java/com/baeldung/properties/ConfigProperties.java
new file mode 100644
index 0000000000..863510738b
--- /dev/null
+++ b/spring-boot/src/main/java/com/baeldung/properties/ConfigProperties.java
@@ -0,0 +1,117 @@
+package com.baeldung.properties;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.Pattern;
+
+import org.hibernate.validator.constraints.Length;
+import org.hibernate.validator.constraints.NotBlank;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.validation.annotation.Validated;
+
+@Configuration
+@PropertySource("classpath:configprops.properties")
+@ConfigurationProperties(prefix = "mail")
+@Validated
+public class ConfigProperties {
+
+ @Validated
+ public static class Credentials {
+
+ @Length(max = 4, min = 1)
+ private String authMethod;
+ private String username;
+ private String password;
+
+ public String getAuthMethod() {
+ return authMethod;
+ }
+
+ public void setAuthMethod(String authMethod) {
+ this.authMethod = authMethod;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+ }
+
+ @NotBlank
+ private String host;
+
+ @Min(1025)
+ @Max(65536)
+ private int port;
+
+ @Pattern(regexp = "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,6}$")
+ private String from;
+
+ private Credentials credentials;
+ private List defaultRecipients;
+ private Map additionalHeaders;
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public String getFrom() {
+ return from;
+ }
+
+ public void setFrom(String from) {
+ this.from = from;
+ }
+
+ public Credentials getCredentials() {
+ return credentials;
+ }
+
+ public void setCredentials(Credentials credentials) {
+ this.credentials = credentials;
+ }
+
+ public List getDefaultRecipients() {
+ return defaultRecipients;
+ }
+
+ public void setDefaultRecipients(List defaultRecipients) {
+ this.defaultRecipients = defaultRecipients;
+ }
+
+ public Map getAdditionalHeaders() {
+ return additionalHeaders;
+ }
+
+ public void setAdditionalHeaders(Map additionalHeaders) {
+ this.additionalHeaders = additionalHeaders;
+ }
+}
diff --git a/spring-boot/src/main/java/com/baeldung/properties/ConfigPropertiesDemoApplication.java b/spring-boot/src/main/java/com/baeldung/properties/ConfigPropertiesDemoApplication.java
new file mode 100644
index 0000000000..ee9671c755
--- /dev/null
+++ b/spring-boot/src/main/java/com/baeldung/properties/ConfigPropertiesDemoApplication.java
@@ -0,0 +1,15 @@
+package com.baeldung.properties;
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.context.annotation.ComponentScan;
+
+@SpringBootApplication
+@ComponentScan(basePackageClasses = { ConfigProperties.class, JsonProperties.class, CustomJsonProperties.class })
+public class ConfigPropertiesDemoApplication {
+ public static void main(String[] args) {
+ new SpringApplicationBuilder(ConfigPropertiesDemoApplication.class).initializers(new JsonPropertyContextInitializer())
+ .run();
+ }
+
+}
diff --git a/spring-boot/src/main/java/com/baeldung/properties/CustomJsonProperties.java b/spring-boot/src/main/java/com/baeldung/properties/CustomJsonProperties.java
new file mode 100644
index 0000000000..084138ec6f
--- /dev/null
+++ b/spring-boot/src/main/java/com/baeldung/properties/CustomJsonProperties.java
@@ -0,0 +1,71 @@
+package com.baeldung.properties;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties(prefix = "custom")
+public class CustomJsonProperties {
+
+ private String host;
+
+ private int port;
+
+ private boolean resend;
+
+ private Person sender;
+
+ public static class Person {
+
+ private String name;
+ private String address;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public boolean isResend() {
+ return resend;
+ }
+
+ public void setResend(boolean resend) {
+ this.resend = resend;
+ }
+
+ public Person getSender() {
+ return sender;
+ }
+
+ public void setSender(Person sender) {
+ this.sender = sender;
+ }
+}
diff --git a/spring-boot/src/main/java/com/baeldung/properties/JsonProperties.java b/spring-boot/src/main/java/com/baeldung/properties/JsonProperties.java
new file mode 100644
index 0000000000..31b3be14b4
--- /dev/null
+++ b/spring-boot/src/main/java/com/baeldung/properties/JsonProperties.java
@@ -0,0 +1,64 @@
+package com.baeldung.properties;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.stereotype.Component;
+
+@Component
+@PropertySource(value = "classpath:configprops.json", factory = JsonPropertySourceFactory.class)
+@ConfigurationProperties
+public class JsonProperties {
+
+ private String host;
+
+ private int port;
+
+ private boolean resend;
+
+ private List topics;
+
+ private LinkedHashMap sender;
+
+ public LinkedHashMap getSender() {
+ return sender;
+ }
+
+ public void setSender(LinkedHashMap sender) {
+ this.sender = sender;
+ }
+
+ public List getTopics() {
+ return topics;
+ }
+
+ public void setTopics(List topics) {
+ this.topics = topics;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public boolean isResend() {
+ return resend;
+ }
+
+ public void setResend(boolean resend) {
+ this.resend = resend;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+}
diff --git a/spring-boot/src/main/java/com/baeldung/properties/JsonPropertyContextInitializer.java b/spring-boot/src/main/java/com/baeldung/properties/JsonPropertyContextInitializer.java
new file mode 100644
index 0000000000..0aee149123
--- /dev/null
+++ b/spring-boot/src/main/java/com/baeldung/properties/JsonPropertyContextInitializer.java
@@ -0,0 +1,68 @@
+package com.baeldung.properties;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.springframework.context.ApplicationContextInitializer;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.MapPropertySource;
+import org.springframework.core.env.PropertySource;
+import org.springframework.core.io.Resource;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class JsonPropertyContextInitializer implements ApplicationContextInitializer {
+
+ private final static String CUSTOM_PREFIX = "custom.";
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
+ try {
+ Resource resource = configurableApplicationContext.getResource("classpath:configprops.json");
+ Map readValue = new ObjectMapper().readValue(resource.getInputStream(), Map.class);
+ Set set = readValue.entrySet();
+ List propertySources = convertEntrySet(set, Optional.empty());
+ for (PropertySource propertySource : propertySources) {
+ configurableApplicationContext.getEnvironment()
+ .getPropertySources()
+ .addFirst(propertySource);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static List convertEntrySet(Set entrySet, Optional parentKey) {
+ return entrySet.stream()
+ .map((Map.Entry e) -> convertToPropertySourceList(e, parentKey))
+ .flatMap(Collection::stream)
+ .collect(Collectors.toList());
+ }
+
+ private static List convertToPropertySourceList(Map.Entry e, Optional parentKey) {
+ String key = parentKey.map(s -> s + ".")
+ .orElse("") + (String) e.getKey();
+ Object value = e.getValue();
+ return covertToPropertySourceList(key, value);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static List covertToPropertySourceList(String key, Object value) {
+ if (value instanceof LinkedHashMap) {
+ LinkedHashMap map = (LinkedHashMap) value;
+ Set entrySet = map.entrySet();
+ return convertEntrySet(entrySet, Optional.ofNullable(key));
+ }
+ String finalKey = CUSTOM_PREFIX + key;
+ return Collections.singletonList(new MapPropertySource(finalKey, Collections.singletonMap(finalKey, value)));
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot/src/main/java/com/baeldung/properties/JsonPropertySourceFactory.java b/spring-boot/src/main/java/com/baeldung/properties/JsonPropertySourceFactory.java
new file mode 100644
index 0000000000..c14d3faea5
--- /dev/null
+++ b/spring-boot/src/main/java/com/baeldung/properties/JsonPropertySourceFactory.java
@@ -0,0 +1,21 @@
+package com.baeldung.properties;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.springframework.core.env.MapPropertySource;
+import org.springframework.core.env.PropertySource;
+import org.springframework.core.io.support.EncodedResource;
+import org.springframework.core.io.support.PropertySourceFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class JsonPropertySourceFactory implements PropertySourceFactory {
+
+ @Override
+ public PropertySource> createPropertySource(String name, EncodedResource resource) throws IOException {
+ Map readValue = new ObjectMapper().readValue(resource.getInputStream(), Map.class);
+ return new MapPropertySource("json-property", readValue);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot/src/main/java/org/baeldung/properties/ConfigPropertiesDemoApplication.java b/spring-boot/src/main/java/org/baeldung/properties/ConfigPropertiesDemoApplication.java
index cb0304fc41..395d68060b 100644
--- a/spring-boot/src/main/java/org/baeldung/properties/ConfigPropertiesDemoApplication.java
+++ b/spring-boot/src/main/java/org/baeldung/properties/ConfigPropertiesDemoApplication.java
@@ -1,13 +1,15 @@
package org.baeldung.properties;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.ComponentScan;
-@EnableAutoConfiguration
-@ComponentScan(basePackageClasses = ConfigProperties.class)
+@SpringBootApplication
+@ComponentScan(basePackageClasses = { ConfigProperties.class, JsonProperties.class, CustomJsonProperties.class })
public class ConfigPropertiesDemoApplication {
public static void main(String[] args) {
- SpringApplication.run(ConfigPropertiesDemoApplication.class);
+ new SpringApplicationBuilder(ConfigPropertiesDemoApplication.class).initializers(new JsonPropertyContextInitializer())
+ .run();
}
+
}
diff --git a/spring-boot/src/main/java/org/baeldung/properties/CustomJsonProperties.java b/spring-boot/src/main/java/org/baeldung/properties/CustomJsonProperties.java
new file mode 100644
index 0000000000..3fae8a8e98
--- /dev/null
+++ b/spring-boot/src/main/java/org/baeldung/properties/CustomJsonProperties.java
@@ -0,0 +1,71 @@
+package org.baeldung.properties;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties(prefix = "custom")
+public class CustomJsonProperties {
+
+ private String host;
+
+ private int port;
+
+ private boolean resend;
+
+ private Person sender;
+
+ public static class Person {
+
+ private String name;
+ private String address;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public boolean isResend() {
+ return resend;
+ }
+
+ public void setResend(boolean resend) {
+ this.resend = resend;
+ }
+
+ public Person getSender() {
+ return sender;
+ }
+
+ public void setSender(Person sender) {
+ this.sender = sender;
+ }
+}
diff --git a/spring-boot/src/main/java/org/baeldung/properties/JsonProperties.java b/spring-boot/src/main/java/org/baeldung/properties/JsonProperties.java
new file mode 100644
index 0000000000..5c31cd1344
--- /dev/null
+++ b/spring-boot/src/main/java/org/baeldung/properties/JsonProperties.java
@@ -0,0 +1,64 @@
+package org.baeldung.properties;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.stereotype.Component;
+
+@Component
+@PropertySource(value = "classpath:configprops.json", factory = JsonPropertySourceFactory.class)
+@ConfigurationProperties
+public class JsonProperties {
+
+ private String host;
+
+ private int port;
+
+ private boolean resend;
+
+ private List topics;
+
+ private LinkedHashMap sender;
+
+ public LinkedHashMap getSender() {
+ return sender;
+ }
+
+ public void setSender(LinkedHashMap sender) {
+ this.sender = sender;
+ }
+
+ public List getTopics() {
+ return topics;
+ }
+
+ public void setTopics(List topics) {
+ this.topics = topics;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public boolean isResend() {
+ return resend;
+ }
+
+ public void setResend(boolean resend) {
+ this.resend = resend;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+}
diff --git a/spring-boot/src/main/java/org/baeldung/properties/JsonPropertyContextInitializer.java b/spring-boot/src/main/java/org/baeldung/properties/JsonPropertyContextInitializer.java
new file mode 100644
index 0000000000..fd9b3f35a5
--- /dev/null
+++ b/spring-boot/src/main/java/org/baeldung/properties/JsonPropertyContextInitializer.java
@@ -0,0 +1,68 @@
+package org.baeldung.properties;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.springframework.context.ApplicationContextInitializer;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.MapPropertySource;
+import org.springframework.core.env.PropertySource;
+import org.springframework.core.io.Resource;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class JsonPropertyContextInitializer implements ApplicationContextInitializer {
+
+ private final static String CUSTOM_PREFIX = "custom.";
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
+ try {
+ Resource resource = configurableApplicationContext.getResource("classpath:configprops.json");
+ Map readValue = new ObjectMapper().readValue(resource.getInputStream(), Map.class);
+ Set set = readValue.entrySet();
+ List propertySources = convertEntrySet(set, Optional.empty());
+ for (PropertySource propertySource : propertySources) {
+ configurableApplicationContext.getEnvironment()
+ .getPropertySources()
+ .addFirst(propertySource);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static List convertEntrySet(Set entrySet, Optional parentKey) {
+ return entrySet.stream()
+ .map((Map.Entry e) -> convertToPropertySourceList(e, parentKey))
+ .flatMap(Collection::stream)
+ .collect(Collectors.toList());
+ }
+
+ private static List convertToPropertySourceList(Map.Entry e, Optional parentKey) {
+ String key = parentKey.map(s -> s + ".")
+ .orElse("") + (String) e.getKey();
+ Object value = e.getValue();
+ return covertToPropertySourceList(key, value);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static List covertToPropertySourceList(String key, Object value) {
+ if (value instanceof LinkedHashMap) {
+ LinkedHashMap map = (LinkedHashMap) value;
+ Set entrySet = map.entrySet();
+ return convertEntrySet(entrySet, Optional.ofNullable(key));
+ }
+ String finalKey = CUSTOM_PREFIX + key;
+ return Collections.singletonList(new MapPropertySource(finalKey, Collections.singletonMap(finalKey, value)));
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot/src/main/java/org/baeldung/properties/JsonPropertySourceFactory.java b/spring-boot/src/main/java/org/baeldung/properties/JsonPropertySourceFactory.java
new file mode 100644
index 0000000000..9578179519
--- /dev/null
+++ b/spring-boot/src/main/java/org/baeldung/properties/JsonPropertySourceFactory.java
@@ -0,0 +1,21 @@
+package org.baeldung.properties;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.springframework.core.env.MapPropertySource;
+import org.springframework.core.env.PropertySource;
+import org.springframework.core.io.support.EncodedResource;
+import org.springframework.core.io.support.PropertySourceFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class JsonPropertySourceFactory implements PropertySourceFactory {
+
+ @Override
+ public PropertySource> createPropertySource(String name, EncodedResource resource) throws IOException {
+ Map readValue = new ObjectMapper().readValue(resource.getInputStream(), Map.class);
+ return new MapPropertySource("json-property", readValue);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot/src/main/resources/configprops.json b/spring-boot/src/main/resources/configprops.json
new file mode 100644
index 0000000000..1602663775
--- /dev/null
+++ b/spring-boot/src/main/resources/configprops.json
@@ -0,0 +1,10 @@
+{
+ "host" : "mailer@mail.com",
+ "port" : 9090,
+ "resend" : true,
+ "topics" : ["spring", "boot"],
+ "sender" : {
+ "name": "sender",
+ "address": "street"
+ }
+}
diff --git a/spring-boot/src/test/java/com/baeldung/properties/ConfigPropertiesIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/properties/ConfigPropertiesIntegrationTest.java
new file mode 100644
index 0000000000..3a4b6551b1
--- /dev/null
+++ b/spring-boot/src/test/java/com/baeldung/properties/ConfigPropertiesIntegrationTest.java
@@ -0,0 +1,45 @@
+package com.baeldung.properties;
+
+import org.baeldung.properties.ConfigProperties;
+import org.baeldung.properties.ConfigPropertiesDemoApplication;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = ConfigPropertiesDemoApplication.class)
+@TestPropertySource("classpath:configprops-test.properties")
+public class ConfigPropertiesIntegrationTest {
+
+ @Autowired
+ private ConfigProperties properties;
+
+ @Test
+ public void whenSimplePropertyQueriedthenReturnsProperty() throws Exception {
+ Assert.assertTrue("From address is read as null!", properties.getFrom() != null);
+ }
+
+ @Test
+ public void whenListPropertyQueriedthenReturnsProperty() throws Exception {
+ Assert.assertTrue("Couldn't bind list property!", properties.getDefaultRecipients().size() == 2);
+ Assert.assertTrue("Incorrectly bound list property. Expected 2 entries!", properties.getDefaultRecipients().size() == 2);
+ }
+
+ @Test
+ public void whenMapPropertyQueriedthenReturnsProperty() throws Exception {
+ Assert.assertTrue("Couldn't bind map property!", properties.getAdditionalHeaders() != null);
+ Assert.assertTrue("Incorrectly bound map property. Expected 3 Entries!", properties.getAdditionalHeaders().size() == 3);
+ }
+
+ @Test
+ public void whenObjectPropertyQueriedthenReturnsProperty() throws Exception {
+ Assert.assertTrue("Couldn't bind map property!", properties.getCredentials() != null);
+ Assert.assertTrue("Incorrectly bound object property!", properties.getCredentials().getAuthMethod().equals("SHA1"));
+ Assert.assertTrue("Incorrectly bound object property!", properties.getCredentials().getUsername().equals("john"));
+ Assert.assertTrue("Incorrectly bound object property!", properties.getCredentials().getPassword().equals("password"));
+ }
+}
diff --git a/spring-boot/src/test/java/com/baeldung/properties/JsonPropertiesIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/properties/JsonPropertiesIntegrationTest.java
new file mode 100644
index 0000000000..48c551d1dd
--- /dev/null
+++ b/spring-boot/src/test/java/com/baeldung/properties/JsonPropertiesIntegrationTest.java
@@ -0,0 +1,63 @@
+package com.baeldung.properties;
+
+import java.util.Arrays;
+
+import org.baeldung.properties.ConfigPropertiesDemoApplication;
+import org.baeldung.properties.CustomJsonProperties;
+import org.baeldung.properties.JsonProperties;
+import org.baeldung.properties.JsonPropertyContextInitializer;
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@ContextConfiguration(classes = ConfigPropertiesDemoApplication.class, initializers = JsonPropertyContextInitializer.class)
+public class JsonPropertiesIntegrationTest {
+
+ @Autowired
+ private JsonProperties jsonProperties;
+
+ @Autowired
+ private CustomJsonProperties customJsonProperties;
+
+ @Test
+ public void whenPropertiesLoadedViaJsonPropertySource_thenLoadFlatValues() {
+ Assert.assertEquals("mailer@mail.com", jsonProperties.getHost());
+ Assert.assertEquals(9090, jsonProperties.getPort());
+ Assert.assertTrue(jsonProperties.isResend());
+ }
+
+ @Test
+ public void whenPropertiesLoadedViaJsonPropertySource_thenLoadListValues() {
+ Assert.assertThat(jsonProperties.getTopics(), Matchers.is(Arrays.asList("spring", "boot")));
+ }
+
+ @Test
+ public void whenPropertiesLoadedViaJsonPropertySource_thenNestedLoadedAsMap() {
+ Assert.assertEquals("sender", jsonProperties.getSender()
+ .get("name"));
+ Assert.assertEquals("street", jsonProperties.getSender()
+ .get("address"));
+ }
+
+ @Test
+ public void whenLoadedIntoEnvironment_thenFlatValuesPopulated() {
+ Assert.assertEquals("mailer@mail.com", customJsonProperties.getHost());
+ Assert.assertEquals(9090, customJsonProperties.getPort());
+ Assert.assertTrue(customJsonProperties.isResend());
+ }
+
+ @Test
+ public void whenLoadedIntoEnvironment_thenValuesLoadedIntoClassObject() {
+ Assert.assertNotNull(customJsonProperties.getSender());
+ Assert.assertEquals("sender", customJsonProperties.getSender()
+ .getName());
+ Assert.assertEquals("street", customJsonProperties.getSender()
+ .getAddress());
+ }
+
+}
diff --git a/spring-boot/src/test/java/org/baeldung/properties/JsonPropertiesIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/properties/JsonPropertiesIntegrationTest.java
new file mode 100644
index 0000000000..e3d4c62953
--- /dev/null
+++ b/spring-boot/src/test/java/org/baeldung/properties/JsonPropertiesIntegrationTest.java
@@ -0,0 +1,59 @@
+package org.baeldung.properties;
+
+import java.util.Arrays;
+
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@ContextConfiguration(classes = ConfigPropertiesDemoApplication.class, initializers = JsonPropertyContextInitializer.class)
+public class JsonPropertiesIntegrationTest {
+
+ @Autowired
+ private JsonProperties jsonProperties;
+
+ @Autowired
+ private CustomJsonProperties customJsonProperties;
+
+ @Test
+ public void whenPropertiesLoadedViaJsonPropertySource_thenLoadFlatValues() {
+ Assert.assertEquals("mailer@mail.com", jsonProperties.getHost());
+ Assert.assertEquals(9090, jsonProperties.getPort());
+ Assert.assertTrue(jsonProperties.isResend());
+ }
+
+ @Test
+ public void whenPropertiesLoadedViaJsonPropertySource_thenLoadListValues() {
+ Assert.assertThat(jsonProperties.getTopics(), Matchers.is(Arrays.asList("spring", "boot")));
+ }
+
+ @Test
+ public void whenPropertiesLoadedViaJsonPropertySource_thenNestedLoadedAsMap() {
+ Assert.assertEquals("sender", jsonProperties.getSender()
+ .get("name"));
+ Assert.assertEquals("street", jsonProperties.getSender()
+ .get("address"));
+ }
+
+ @Test
+ public void whenLoadedIntoEnvironment_thenFlatValuesPopulated() {
+ Assert.assertEquals("mailer@mail.com", customJsonProperties.getHost());
+ Assert.assertEquals(9090, customJsonProperties.getPort());
+ Assert.assertTrue(customJsonProperties.isResend());
+ }
+
+ @Test
+ public void whenLoadedIntoEnvironment_thenValuesLoadedIntoClassObject() {
+ Assert.assertNotNull(customJsonProperties.getSender());
+ Assert.assertEquals("sender", customJsonProperties.getSender()
+ .getName());
+ Assert.assertEquals("street", customJsonProperties.getSender()
+ .getAddress());
+ }
+
+}
diff --git a/spring-cloud/pom.xml b/spring-cloud/pom.xml
index 7d180047de..376d8099ed 100644
--- a/spring-cloud/pom.xml
+++ b/spring-cloud/pom.xml
@@ -33,6 +33,8 @@
spring-cloud-contract
spring-cloud-kubernetes
spring-cloud-archaius
+ spring-cloud-functions
+ spring-cloud-vault
diff --git a/spring-cloud/spring-cloud-functions/pom.xml b/spring-cloud/spring-cloud-functions/pom.xml
new file mode 100644
index 0000000000..e3c17329d0
--- /dev/null
+++ b/spring-cloud/spring-cloud-functions/pom.xml
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+ spring-cloud-functions
+ pom
+
+
+ parent-boot-2
+ com.baeldung
+ 0.0.1-SNAPSHOT
+ ../../parent-boot-2
+
+
+
+ spring-cloud-function-aws
+
+
+
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/pom.xml b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/pom.xml
new file mode 100644
index 0000000000..8b2b0ad385
--- /dev/null
+++ b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/pom.xml
@@ -0,0 +1,94 @@
+
+
+ 4.0.0
+
+ com.baeldung.spring
+ cloudfunction-aws
+ 0.0.1-SNAPSHOT
+ jar
+
+ cloudfunction-aws
+ Demo project for Spring Cloud Function
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.0.4.RELEASE
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ 1.0.1.RELEASE
+ 2.0.2
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-function-adapter-aws
+ ${spring-cloud-function.version}
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-function-web
+ 1.0.1.RELEASE
+
+
+ com.amazonaws
+ aws-lambda-java-events
+ ${aws-lambda-events.version}
+ provided
+
+
+ com.amazonaws
+ aws-lambda-java-core
+ 1.1.0
+ provided
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+
+ true
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.springframework.boot.experimental
+ spring-boot-thin-layout
+ 1.0.10.RELEASE
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+ false
+ true
+ aws
+
+
+
+
+
+
diff --git a/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/CloudFunctionAwsApplication.java b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/CloudFunctionAwsApplication.java
new file mode 100644
index 0000000000..cc8f11beca
--- /dev/null
+++ b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/CloudFunctionAwsApplication.java
@@ -0,0 +1,23 @@
+package com.baeldung.spring.cloudfunction;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+@SpringBootApplication
+public class CloudFunctionAwsApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(CloudFunctionAwsApplication.class, args);
+ }
+
+ @Bean
+ public Function reverseString() {
+ return value -> new StringBuilder(value).reverse().toString();
+ }
+
+}
diff --git a/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/StringReverseHandler.java b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/StringReverseHandler.java
new file mode 100644
index 0000000000..d103bc98d9
--- /dev/null
+++ b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/StringReverseHandler.java
@@ -0,0 +1,7 @@
+package com.baeldung.spring.cloudfunction;
+
+import org.springframework.cloud.function.adapter.aws.SpringBootRequestHandler;
+
+public class StringReverseHandler extends SpringBootRequestHandler {
+
+}
diff --git a/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/functions/Greeter.java b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/functions/Greeter.java
new file mode 100644
index 0000000000..124aefe56e
--- /dev/null
+++ b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/java/com/baeldung/spring/cloudfunction/functions/Greeter.java
@@ -0,0 +1,11 @@
+package com.baeldung.spring.cloudfunction.functions;
+
+import java.util.function.Function;
+
+public class Greeter implements Function {
+
+ @Override
+ public String apply(String s) {
+ return "Hello " + s + ", and welcome to Spring Cloud Function!!!";
+ }
+}
diff --git a/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/resources/application.properties b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/resources/application.properties
new file mode 100644
index 0000000000..14426a848c
--- /dev/null
+++ b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/main/resources/application.properties
@@ -0,0 +1 @@
+spring.cloud.function.scan.packages: com.baeldung.spring.cloudfunction.functions
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/test/java/com/baeldung/spring/cloudfunction/CloudFunctionApplicationTests.java b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/test/java/com/baeldung/spring/cloudfunction/CloudFunctionApplicationTests.java
new file mode 100644
index 0000000000..01199475fb
--- /dev/null
+++ b/spring-cloud/spring-cloud-functions/spring-cloud-function-aws/src/test/java/com/baeldung/spring/cloudfunction/CloudFunctionApplicationTests.java
@@ -0,0 +1,33 @@
+package com.baeldung.spring.cloudfunction;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.boot.web.server.LocalServerPort;
+
+import static org.assertj.core.api.Java6Assertions.assertThat;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+public class CloudFunctionApplicationTests {
+
+ @LocalServerPort
+ private int port;
+
+ @Autowired
+ private TestRestTemplate testRestTemplate;
+
+ @Test
+ public void givenAString_whenReverseStringCloudFunctionInvoked_thenStringIsReversed() {
+ assertThat(this.testRestTemplate.getForObject("http://localhost:" + port + "/reverseString/HelloWorld", String.class)).isEqualTo("dlroWolleH");
+ }
+
+ @Test
+ public void givenAString_whenGreeterCloudFunctionInvoked_thenPrintsGreeting() {
+ assertThat(this.testRestTemplate.getForObject("http://localhost:" + port + "/greeter/BaeldungUser", String.class)).isEqualTo("Hello BaeldungUser, and welcome to Spring Cloud Function!!!");
+ }
+
+}
diff --git a/spring-cloud/spring-cloud-stream-starters/twitter/twitter b/spring-cloud/spring-cloud-stream-starters/twitter/twitter
deleted file mode 160000
index f9673ef0c1..0000000000
--- a/spring-cloud/spring-cloud-stream-starters/twitter/twitter
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit f9673ef0c11c51b327555aaca61ee196935f998b
diff --git a/spring-cloud/spring-cloud-vault/.gitignore b/spring-cloud/spring-cloud-vault/.gitignore
new file mode 100644
index 0000000000..e6237b6f81
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/.gitignore
@@ -0,0 +1,29 @@
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/build/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+## Extra
+/vault-data/
+*.log
diff --git a/spring-cloud/spring-cloud-vault/database-setup.sql b/spring-cloud/spring-cloud-vault/database-setup.sql
new file mode 100644
index 0000000000..4bb1293f74
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/database-setup.sql
@@ -0,0 +1,20 @@
+--
+-- Sample schema for testing vault database secrets
+--
+create schema fakebank;
+use fakebank;
+create table account(
+ id decimal(16,0),
+ name varchar(30),
+ branch_id decimal(16,0),
+ customer_id decimal(16,0),
+ primary key (id));
+
+--
+-- MySQL user that will be used by Vault to create other users on demand
+--
+create user 'fakebank-admin'@'%' identified by 'Sup&rSecre7!'
+grant all privileges on fakebank.* to 'fakebank-admin'@'%' with grant option;
+grant create user on *.* to 'fakebank-admin' with grant option;
+
+flush privileges;
diff --git a/spring-cloud/spring-cloud-vault/pom.xml b/spring-cloud/spring-cloud-vault/pom.xml
new file mode 100644
index 0000000000..68b8e44875
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/pom.xml
@@ -0,0 +1,87 @@
+
+
+ 4.0.0
+
+ org.baeldung.spring.cloud
+ spring-cloud-vault
+ jar
+
+ spring-cloud-vault
+ Demo project for Spring Boot
+
+
+ com.baeldung
+ parent-boot-2
+ 0.0.1-SNAPSHOT
+ ../../parent-boot-2
+
+
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ Finchley.SR1
+
+
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-vault-config
+
+
+
+ org.springframework.cloud
+ spring-cloud-vault-config-databases
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+ mysql
+ mysql-connector-java
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
diff --git a/spring-cloud/spring-cloud-vault/sample-policy.hcl b/spring-cloud/spring-cloud-vault/sample-policy.hcl
new file mode 100644
index 0000000000..554888661e
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/sample-policy.hcl
@@ -0,0 +1,6 @@
+path "secret/fakebank" {
+ capabilities = ["read"]
+ allowed_parameters = {
+ "api_key" = []
+ }
+}
diff --git a/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplication.java b/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplication.java
new file mode 100644
index 0000000000..81ece1ca4c
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/src/main/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplication.java
@@ -0,0 +1,12 @@
+package org.baeldung.spring.cloud.vaultsample;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class VaultSampleApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(VaultSampleApplication.class, args);
+ }
+}
diff --git a/spring-cloud/spring-cloud-vault/src/main/resources/application.yml b/spring-cloud/spring-cloud-vault/src/main/resources/application.yml
new file mode 100644
index 0000000000..3d347ec855
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/src/main/resources/application.yml
@@ -0,0 +1,6 @@
+spring:
+ application:
+ name: fakebank
+
+ datasource:
+ url: jdbc:mysql://localhost:3306/fakebank
diff --git a/spring-cloud/spring-cloud-vault/src/main/resources/bootstrap.yml b/spring-cloud/spring-cloud-vault/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000000..1e837c4920
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/src/main/resources/bootstrap.yml
@@ -0,0 +1,37 @@
+spring:
+ cloud:
+ vault:
+ uri: https://localhost:8200
+ connection-timeout: 5000
+ read-timeout: 15000
+ config:
+ order: -10
+
+ ssl:
+ trust-store: classpath:/vault.jks
+ trust-store-password: changeit
+
+ generic:
+ enabled: true
+ application-name: fakebank
+
+ kv:
+ enabled: false
+ backend: kv
+ application-name: fakebank
+
+ database:
+ enabled: true
+ role: fakebank-accounts-rw
+# backend: database
+# username-property: spring.datasource.username
+# password-property: spring.datasource.password
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-vault/src/main/resources/vault.jks b/spring-cloud/spring-cloud-vault/src/main/resources/vault.jks
new file mode 100644
index 0000000000..7090707543
Binary files /dev/null and b/spring-cloud/spring-cloud-vault/src/main/resources/vault.jks differ
diff --git a/spring-cloud/spring-cloud-vault/src/test/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplicationLiveTest.java b/spring-cloud/spring-cloud-vault/src/test/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplicationLiveTest.java
new file mode 100644
index 0000000000..7a9c5ba11a
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/src/test/java/org/baeldung/spring/cloud/vaultsample/VaultSampleApplicationLiveTest.java
@@ -0,0 +1,66 @@
+package org.baeldung.spring.cloud.vaultsample;
+
+import static org.junit.Assert.assertEquals;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import javax.sql.DataSource;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.core.env.Environment;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class VaultSampleApplicationLiveTest {
+
+ @Autowired
+ Environment env;
+
+ @Autowired
+ DataSource datasource;
+
+
+ @Test
+ public void whenGenericBackendEnabled_thenEnvHasAccessToVaultSecrets() {
+
+ String fooValue = env.getProperty("foo");
+ assertEquals("test-bar", fooValue);
+
+ }
+
+ @Test
+ public void whenKvBackendEnabled_thenEnvHasAccessToVaultSecrets() {
+
+ String fooValue = env.getProperty("foo.versioned");
+ assertEquals("bar1", fooValue);
+
+
+ }
+
+
+ @Test
+ public void whenDatabaseBackendEnabled_thenDatasourceUsesVaultCredentials() {
+
+ try (Connection c = datasource.getConnection()) {
+
+ ResultSet rs = c.createStatement()
+ .executeQuery("select 1");
+
+ rs.next();
+ Long value = rs.getLong(1);
+
+ assertEquals(Long.valueOf(1), value);
+
+ } catch (SQLException sex) {
+ throw new RuntimeException(sex);
+ }
+
+ }
+
+}
diff --git a/spring-cloud/spring-cloud-vault/src/test/resources/bootstrap.properties b/spring-cloud/spring-cloud-vault/src/test/resources/bootstrap.properties
new file mode 100644
index 0000000000..8c54227dda
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/src/test/resources/bootstrap.properties
@@ -0,0 +1,3 @@
+spring.cloud.vault.token=b93d1b0d-15b5-f69e-d311-352a65fa7bc8
+
+logging.level.org.springframework=INFO
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-vault/src/test/resources/vault.jks b/spring-cloud/spring-cloud-vault/src/test/resources/vault.jks
new file mode 100644
index 0000000000..7090707543
Binary files /dev/null and b/spring-cloud/spring-cloud-vault/src/test/resources/vault.jks differ
diff --git a/spring-cloud/spring-cloud-vault/src/test/vault-config/localhost.cert b/spring-cloud/spring-cloud-vault/src/test/vault-config/localhost.cert
new file mode 100644
index 0000000000..6a598df419
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/src/test/vault-config/localhost.cert
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC+zCCAeOgAwIBAgIJAKoy5OBgOKYwMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV
+BAMMCWxvY2FsaG9zdDAeFw0xODA4MDkwMTM1MzJaFw0yODA4MDYwMTM1MzJaMBQx
+EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMXiHqB5dYdxJ1+abSG55gb3NNo3fzNbkjp/tAIl1FUeyCyyP/yERrkUkhFj
+4gg/q1YHUO/ftc0PdL/JBaVBTKnzsxgp7hY/dUEkZqXZ649X0UrJIRd13w5N71cL
+P1+PjCrqokMVceU18kK7CyaOmiTKYFmt/RTJQLmFQspmJXNSiq7zUvAgyvoY5TzJ
+n7MuSobHXq17pnlm+XbnAgDJUt9yR6BC2dFF20iZU4uTXy2VRngfLey3p+6in0TO
+jD4cEMJqwgUbjiI8m/hESCketVkq0W0qkkVfWBNzz5qqGHNRbhZBwT7SM0MuXum+
+qEY7n7jcQAk5BDb613liVQjQ0tkCAwEAAaNQME4wHQYDVR0OBBYEFHYjQ0/HJgXd
+BnqM4jLPjmygfi8fMB8GA1UdIwQYMBaAFHYjQ0/HJgXdBnqM4jLPjmygfi8fMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBABSf++sinLT9dFnC+B6ut5Zp
+haTL7PA1/CdmhTdE2vlFPGGw2BD4c/gphBsHKSNHE96irTqFXI/kl6labQpZ5P8G
+JORLfaAyl58UT1FayxL4ISzwsp+UrqO60vxkYyLkbEJjuaxIv11oOoFDIp5oBTqe
+BVoCfcTjYtTr+IwwlypLPrVTnDNGX5oPIBbTUFvR0t5RaLZgmXLT78ERhWOLINqh
+Yi6j7fYaRm/C5IQ8N/TASot7V0SMH2Rt6PrzJb5SLV8r+yozg2BSfU6hZUyKwABR
+N3zppKvKzdhlVo9OuSW3x4Tb3V+CVE/8CmTwRfhab9SCmvmaa2FxI+8/2OPVWDU=
+-----END CERTIFICATE-----
diff --git a/spring-cloud/spring-cloud-vault/src/test/vault-config/localhost.key b/spring-cloud/spring-cloud-vault/src/test/vault-config/localhost.key
new file mode 100644
index 0000000000..eba611823a
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/src/test/vault-config/localhost.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAxeIeoHl1h3EnX5ptIbnmBvc02jd/M1uSOn+0AiXUVR7ILLI/
+/IRGuRSSEWPiCD+rVgdQ79+1zQ90v8kFpUFMqfOzGCnuFj91QSRmpdnrj1fRSskh
+F3XfDk3vVws/X4+MKuqiQxVx5TXyQrsLJo6aJMpgWa39FMlAuYVCymYlc1KKrvNS
+8CDK+hjlPMmfsy5KhsderXumeWb5ducCAMlS33JHoELZ0UXbSJlTi5NfLZVGeB8t
+7Len7qKfRM6MPhwQwmrCBRuOIjyb+ERIKR61WSrRbSqSRV9YE3PPmqoYc1FuFkHB
+PtIzQy5e6b6oRjufuNxACTkENvrXeWJVCNDS2QIDAQABAoIBACEyB5VACtlHwCUn
+kLshplbwzWr1+F6zM9qgZaAenHoTCd2FoXpI7lxJ+R71tItRsvphi9BRpPvbZehu
+XoYUaDnyac7Z6djNmGvvIVEdN4j6YF+9UdHPsjWCGW5uspjjSc5BQisiw9KBtDxB
+iGNVdMJLONKSf2wnPrZgho3RiOLJX/poPyGTkMHuhBVvo4oy7Ax3XalaAcufgqwm
+YBQJ1Tka+33EUiLkxzJTXxNbIAI2scP8jhGn6mokS0V4gZPxJKUZEyydXRWwi6ex
+ua/7q76ELJS5b+xKRYfGsvavFDx8R+LqX8oegALD33ki3rm1MQW7GmikRL98+EVW
+Q9mQsqECgYEA/IrP8vycbJOgn1vriNItFcZtczSBlrXCRF0up2cqKMs9c+T5i51x
+ZKXK5lo3DfMT+YDM+iiGZ9+vM0UA2VxbFD3XV9mQDBaNC+Duknqxx+OLmWva9YwR
+nMaevqVV9LCn+GgUcK+IygEnpzpdP4q8YcXAfGAnZgnihN/AUYAaB70CgYEAyJe4
+yO0S9gAH5aoDdooL0YXrH/Dzd+fAgNsawLhoOltcoZqZFWeAllM0GsrCpfTRltuy
+dn9ca3YK0GlWl7h5rDle1HO3nhp1FcpeG1oxmkeQta3PG66uUuMccTAljCLFrEe3
+DguH8+qdjhLk+ZnUB9AVkS79pzdwuEHVljCK600CgYB6mMygkh9B2lzkX9Q0xItc
+gcqKXdf3GN9pHq9SVxOxYBDCHUtDirgMeyvHrc4COJneyrc3TcsJzB4aToo9+sbA
+SdErdZOnOp9YP+axN1zsw7r2TNSr1UaLjCRuOodC1SuFvMkHdz95iRv946h2+1u+
+PyjVeDxIHc5YYOLU7dI1JQKBgQDF5KDBYNm25brkwcCe3nvgXfzjyyN25KUOupn/
+DS6Oe/m72Lgz3KOIKleaIvS7IvbunJnIu8dioNb0Wye5kJ5A4WyDrhG1IabnM3l6
+BJYw/W9vPSS4y7FhRnuV0wkH4nofh7S5X3jlk02Sj2NkN3Vtq8TLMY++uzwyG4jq
+ncM/dQKBgQC+6mA5OfbVN4lRn+zrSiIH5gpvZYPh9wXeTnDWHa13sJsu3e8AQxtk
+TfE0W13UV5jhGL8Wvyyxn+doGFTdcZapOlwuoQ6RcgHcVQm2sOl60GAa4idmm0A6
+TcgnIOTyVRlNBoWLCfN83BlGz4gcDpnuZZ/0JuguixgLS323hQlLvg==
+-----END RSA PRIVATE KEY-----
diff --git a/spring-cloud/spring-cloud-vault/src/test/vault-config/vault-test.hcl b/spring-cloud/spring-cloud-vault/src/test/vault-config/vault-test.hcl
new file mode 100644
index 0000000000..c880f2d744
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/src/test/vault-config/vault-test.hcl
@@ -0,0 +1,20 @@
+/*
+ * Sample configuration file for tests
+ */
+
+// Enable UI
+ui = true
+
+// Filesystem storage
+storage "file" {
+ path = "./vault-data"
+}
+
+// TCP Listener using a self-signed certificate
+listener "tcp" {
+ address = "127.0.0.1:8200"
+ tls_cert_file = "./src/test/vault-config/localhost.cert"
+ tls_key_file = "./src/test/vault-config/localhost.key"
+}
+
+
diff --git a/spring-cloud/spring-cloud-vault/vault-cheatsheet.txt b/spring-cloud/spring-cloud-vault/vault-cheatsheet.txt
new file mode 100644
index 0000000000..b965a95321
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/vault-cheatsheet.txt
@@ -0,0 +1,82 @@
+== Vault server bootstrap
+
+1. Run vaul-start in one shell
+
+2. Open another shell and execute the command below:
+> vault operator init
+
+Vault will output the unseal keys and root token: STORE THEM SAFELY !!!
+
+Example output:
+Unseal Key 1: OfCseaSZzjTZmrxhfx+5clKobwLGCNiJdAlfixSG9E3o
+Unseal Key 2: iplVLPTHW0n0WL5XuI6QWwyNtWbKTek1SoKcG0gR7vdT
+Unseal Key 3: K0TleK3OYUvWFF+uIDsQuf5a+/gkv1PtZ3O47ornzRoF
+Unseal Key 4: +5zhysLAO4hIdZs0kiZpkrRovw11uQacfloiBwnZBJA/
+Unseal Key 5: GDwSq18lXV3Cw4MoHsKIH137kuI0mdl36UiD9WxOdulc
+
+Initial Root Token: d341fdaf-1cf9-936a-3c38-cf5eec94b5c0
+
+...
+
+== Admin token setup
+
+1. Set the VAULT_TOKEN environment variable with the root token value
+export VAULT_TOKEN=d341fdaf-1cf9-936a-3c38-cf5eec94b5c0 (Linux)
+set VAULT_TOKEN=d341fdaf-1cf9-936a-3c38-cf5eec94b5c0 (Windows)
+
+2. Create another admin token
+
+>vault token create -display-name=admin
+Key Value
+--- -----
+token 3779c3ca-9f5e-1d8f-3842-efa96d88de43 <=== this is the new root token
+token_accessor 2dfa4031-973b-cf88-c749-ee6f520ecaea
+token_duration ∞
+token_renewable false
+token_policies ["root"]
+identity_policies []
+policies ["root"]
+
+3. Create ~/.vault-secret with your root token
+4. Unset the VAULT_TOKEN environment variable !
+
+=== Test DB setup (MySQL only, for now)
+
+1. Create test db
+2. Create admin account used to create dynamic accounts:
+
+create schema fakebank;
+create user 'fakebank-admin'@'%' identified by 'Sup&rSecre7!'
+grant all privileges on fakebank.* to 'fakebank-admin'@'%' with grant option;
+grant create user on *.* to 'fakebank-admin' with grant option;
+flush privileges;
+
+
+=== Database secret backend setup
+> vault secrets enable database
+
+==== Create db configuration
+> vault write database/config/mysql-fakebank ^
+ plugin_name=mysql-legacy-database-plugin ^
+ connection_url="{{username}}:{{password}}@tcp(127.0.0.1:3306)/fakebank" ^
+ allowed_roles="*" ^
+ username="fakebank-admin" ^
+ password="Sup&rSecre7!"
+
+==== Create roles
+> vault write database/roles/fakebank-accounts-ro ^
+ db_name=mysql-fakebank ^
+ creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT ON fakebank.* TO '{{name}}'@'%';" ^
+ default_ttl="1h" ^
+ max_ttl="24h"
+
+> vault write database/roles/fakebank-accounts-rw ^
+ db_name=mysql-fakebank ^
+ creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT SELECT,INSERT,UPDATE ON fakebank.* TO '{{name}}'@'%';" ^
+ default_ttl="1m" ^
+ max_ttl="2m"
+
+=== Get credentials
+> vault read database/creds/fakebank-accounts-rw
+
+
diff --git a/spring-cloud/spring-cloud-vault/vault-env.bat b/spring-cloud/spring-cloud-vault/vault-env.bat
new file mode 100644
index 0000000000..d7aa5da215
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/vault-env.bat
@@ -0,0 +1,5 @@
+@echo off
+echo Setting environment variables to access local vault..
+set VAULT_ADDR=https://localhost:8200
+set VAULT_CACERT=%~dp0%/src/test/vault-config/localhost.cert
+rem set VAULT_TLS_SERVER_NAME=localhost
diff --git a/spring-cloud/spring-cloud-vault/vault-env.sh b/spring-cloud/spring-cloud-vault/vault-env.sh
new file mode 100644
index 0000000000..06077cee2e
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/vault-env.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+echo Setting environment variables to access local vault..
+SCRIPTPATH=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )
+export VAULT_ADDR=https://localhost:8200
+export VAULT_CACERT=$SCRIPTPATH/src/test/vault-config/localhost.cert
+export VAULT_TLS_SERVER_NAME=localhost
diff --git a/spring-cloud/spring-cloud-vault/vault-start.bat b/spring-cloud/spring-cloud-vault/vault-start.bat
new file mode 100644
index 0000000000..e8f6ce4c9f
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/vault-start.bat
@@ -0,0 +1,3 @@
+echo Starting vault server...
+pushd %~dp0%
+vault server -config %~dp0%/src/test/vault-config/vault-test.hcl
diff --git a/spring-cloud/spring-cloud-vault/vault-start.sh b/spring-cloud/spring-cloud-vault/vault-start.sh
new file mode 100644
index 0000000000..d5af7cfee6
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/vault-start.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
+pushd $SCRIPTPATH
+echo Starting vault server...
+vault server -config $SCRIPTPATH/src/test/vault-config/vault-test.hcl
diff --git a/spring-cloud/spring-cloud-vault/vault-unseal.bat b/spring-cloud/spring-cloud-vault/vault-unseal.bat
new file mode 100644
index 0000000000..8133f90892
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/vault-unseal.bat
@@ -0,0 +1,7 @@
+
+call %~dp0%/vault-env.bat
+
+vault operator unseal OfCseaSZzjTZmrxhfx+5clKobwLGCNiJdAlfixSG9E3o
+vault operator unseal iplVLPTHW0n0WL5XuI6QWwyNtWbKTek1SoKcG0gR7vdT
+vault operator unseal iplVLPTHW0n0WL5XuI6QWwyNtWbKTek1SoKcG0gR7vdT
+vault operator unseal K0TleK3OYUvWFF+uIDsQuf5a+/gkv1PtZ3O47ornzRoF
diff --git a/spring-cloud/spring-cloud-vault/vault-unseal.sh b/spring-cloud/spring-cloud-vault/vault-unseal.sh
new file mode 100644
index 0000000000..699b383801
--- /dev/null
+++ b/spring-cloud/spring-cloud-vault/vault-unseal.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
+. $SCRIPTPATH/vault-env.sh
+
+# Please replace the unseal keys below for your own
+vault operator unseal OfCseaSZzjTZmrxhfx+5clKobwLGCNiJdAlfixSG9E3o
+vault operator unseal iplVLPTHW0n0WL5XuI6QWwyNtWbKTek1SoKcG0gR7vdT
+vault operator unseal K0TleK3OYUvWFF+uIDsQuf5a+/gkv1PtZ3O47ornzRoF
diff --git a/spring-core/src/main/java/com/baeldung/dependency/exception/app/PurchaseDeptService.java b/spring-core/src/main/java/com/baeldung/dependency/exception/app/PurchaseDeptService.java
index 1e6fad63aa..e0fe01acdd 100644
--- a/spring-core/src/main/java/com/baeldung/dependency/exception/app/PurchaseDeptService.java
+++ b/spring-core/src/main/java/com/baeldung/dependency/exception/app/PurchaseDeptService.java
@@ -1,13 +1,14 @@
package com.baeldung.dependency.exception.app;
import com.baeldung.dependency.exception.repository.InventoryRepository;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class PurchaseDeptService {
private InventoryRepository repository;
- public PurchaseDeptService(InventoryRepository repository) {
+ public PurchaseDeptService(@Qualifier("dresses") InventoryRepository repository) {
this.repository = repository;
}
}
\ No newline at end of file
diff --git a/spring-core/src/main/java/com/baeldung/dependency/exception/repository/DressRepository.java b/spring-core/src/main/java/com/baeldung/dependency/exception/repository/DressRepository.java
index 4a6c836143..5a1371ce04 100644
--- a/spring-core/src/main/java/com/baeldung/dependency/exception/repository/DressRepository.java
+++ b/spring-core/src/main/java/com/baeldung/dependency/exception/repository/DressRepository.java
@@ -1,9 +1,10 @@
package com.baeldung.dependency.exception.repository;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;
-@Primary
+@Qualifier("dresses")
@Repository
public class DressRepository implements InventoryRepository {
}
diff --git a/spring-core/src/main/java/com/baeldung/dependency/exception/repository/ShoeRepository.java b/spring-core/src/main/java/com/baeldung/dependency/exception/repository/ShoeRepository.java
index 60495914cd..227d8934b6 100644
--- a/spring-core/src/main/java/com/baeldung/dependency/exception/repository/ShoeRepository.java
+++ b/spring-core/src/main/java/com/baeldung/dependency/exception/repository/ShoeRepository.java
@@ -1,7 +1,9 @@
package com.baeldung.dependency.exception.repository;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;
+@Qualifier("shoes")
@Repository
public class ShoeRepository implements InventoryRepository {
}
diff --git a/spring-data-jpa/pom.xml b/spring-data-jpa/pom.xml
index c4893df759..8691ce1f09 100644
--- a/spring-data-jpa/pom.xml
+++ b/spring-data-jpa/pom.xml
@@ -41,6 +41,26 @@
guava
21.0
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+
+
+ org.junit.platform
+ junit-platform-launcher
+ ${junit-platform.version}
+ test
+
\ No newline at end of file
diff --git a/spring-data-jpa/src/main/java/com/baeldung/Application.java b/spring-data-jpa/src/main/java/com/baeldung/Application.java
index 4e14f94311..72d29d9fa5 100644
--- a/spring-data-jpa/src/main/java/com/baeldung/Application.java
+++ b/spring-data-jpa/src/main/java/com/baeldung/Application.java
@@ -1,11 +1,11 @@
package com.baeldung;
-import com.baeldung.dao.repositories.impl.ExtendedRepositoryImpl;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import com.baeldung.dao.repositories.impl.ExtendedRepositoryImpl;
+
@SpringBootApplication
@EnableJpaRepositories(repositoryBaseClass = ExtendedRepositoryImpl.class)
public class Application {
diff --git a/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/InventoryRepository.java b/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/InventoryRepository.java
new file mode 100644
index 0000000000..a575f0b915
--- /dev/null
+++ b/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/InventoryRepository.java
@@ -0,0 +1,7 @@
+package com.baeldung.dao.repositories;
+
+import com.baeldung.domain.MerchandiseEntity;
+import org.springframework.data.repository.CrudRepository;
+
+public interface InventoryRepository extends CrudRepository {
+}
diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate.java
new file mode 100644
index 0000000000..bf6ff0a0b9
--- /dev/null
+++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate.java
@@ -0,0 +1,46 @@
+/**
+ *
+ */
+package com.baeldung.ddd.event;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Transient;
+
+import org.springframework.context.ApplicationEventPublisher;
+
+@Entity
+class Aggregate {
+ @Transient
+ private ApplicationEventPublisher eventPublisher;
+ @Id
+ private long id;
+
+ private Aggregate() {
+ }
+
+ Aggregate(long id, ApplicationEventPublisher eventPublisher) {
+ this.id = id;
+ this.eventPublisher = eventPublisher;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "DomainEntity [id=" + id + "]";
+ }
+
+ void domainOperation() {
+ // some business logic
+ if (eventPublisher != null) {
+ eventPublisher.publishEvent(new DomainEvent());
+ }
+ }
+
+ long getId() {
+ return id;
+ }
+
+}
diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2.java
new file mode 100644
index 0000000000..3d2816299a
--- /dev/null
+++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2.java
@@ -0,0 +1,44 @@
+/**
+ *
+ */
+package com.baeldung.ddd.event;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Transient;
+
+import org.springframework.data.domain.AfterDomainEventPublication;
+import org.springframework.data.domain.DomainEvents;
+
+@Entity
+public class Aggregate2 {
+ @Transient
+ private final Collection domainEvents;
+ @Id
+ @GeneratedValue
+ private long id;
+
+ public Aggregate2() {
+ domainEvents = new ArrayList<>();
+ }
+
+ @AfterDomainEventPublication
+ public void clearEvents() {
+ domainEvents.clear();
+ }
+
+ public void domainOperation() {
+ // some domain operation
+ domainEvents.add(new DomainEvent());
+ }
+
+ @DomainEvents
+ public Collection events() {
+ return domainEvents;
+ }
+
+}
diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2Repository.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2Repository.java
new file mode 100644
index 0000000000..2a95abe347
--- /dev/null
+++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate2Repository.java
@@ -0,0 +1,10 @@
+/**
+ *
+ */
+package com.baeldung.ddd.event;
+
+import org.springframework.data.repository.CrudRepository;
+
+public interface Aggregate2Repository extends CrudRepository {
+
+}
diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3.java
new file mode 100644
index 0000000000..e0c3131b06
--- /dev/null
+++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3.java
@@ -0,0 +1,23 @@
+/**
+ *
+ */
+package com.baeldung.ddd.event;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+import org.springframework.data.domain.AbstractAggregateRoot;
+
+@Entity
+public class Aggregate3 extends AbstractAggregateRoot {
+ @Id
+ @GeneratedValue
+ private long id;
+
+ public void domainOperation() {
+ // some domain operation
+ registerEvent(new DomainEvent());
+ }
+
+}
diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3Repository.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3Repository.java
new file mode 100644
index 0000000000..e442bdb210
--- /dev/null
+++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/Aggregate3Repository.java
@@ -0,0 +1,14 @@
+/**
+ *
+ */
+package com.baeldung.ddd.event;
+
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * @author goobar
+ *
+ */
+public interface Aggregate3Repository extends CrudRepository {
+
+}
diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/AggregateRepository.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/AggregateRepository.java
new file mode 100644
index 0000000000..5a15156d03
--- /dev/null
+++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/AggregateRepository.java
@@ -0,0 +1,10 @@
+/**
+ *
+ */
+package com.baeldung.ddd.event;
+
+import org.springframework.data.repository.CrudRepository;
+
+public interface AggregateRepository extends CrudRepository {
+
+}
diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DddConfig.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DddConfig.java
new file mode 100644
index 0000000000..1315b11875
--- /dev/null
+++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DddConfig.java
@@ -0,0 +1,15 @@
+/**
+ *
+ */
+package com.baeldung.ddd.event;
+
+import org.springframework.boot.SpringBootConfiguration;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.PropertySource;
+
+@SpringBootConfiguration
+@EnableAutoConfiguration
+@PropertySource("classpath:/ddd.properties")
+public class DddConfig {
+
+}
diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainEvent.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainEvent.java
new file mode 100644
index 0000000000..1e6479d4fc
--- /dev/null
+++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainEvent.java
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+package com.baeldung.ddd.event;
+
+class DomainEvent {
+
+}
diff --git a/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainService.java b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainService.java
new file mode 100644
index 0000000000..082c9bd88e
--- /dev/null
+++ b/spring-data-jpa/src/main/java/com/baeldung/ddd/event/DomainService.java
@@ -0,0 +1,31 @@
+/**
+ *
+ */
+package com.baeldung.ddd.event;
+
+import javax.transaction.Transactional;
+
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.stereotype.Service;
+
+@Service
+public class DomainService {
+ private final ApplicationEventPublisher eventPublisher;
+ private final AggregateRepository repository;
+
+ public DomainService(AggregateRepository repository, ApplicationEventPublisher eventPublisher) {
+ this.repository = repository;
+ this.eventPublisher = eventPublisher;
+ }
+
+ @Transactional
+ public void serviceDomainOperation(long entityId) {
+ repository.findById(entityId)
+ .ifPresent(entity -> {
+ entity.domainOperation();
+ repository.save(entity);
+ eventPublisher.publishEvent(new DomainEvent());
+ });
+ }
+
+}
diff --git a/spring-data-jpa/src/main/java/com/baeldung/domain/MerchandiseEntity.java b/spring-data-jpa/src/main/java/com/baeldung/domain/MerchandiseEntity.java
new file mode 100644
index 0000000000..bfc690e0e2
--- /dev/null
+++ b/spring-data-jpa/src/main/java/com/baeldung/domain/MerchandiseEntity.java
@@ -0,0 +1,66 @@
+package com.baeldung.domain;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import java.math.BigDecimal;
+
+@Entity
+public class MerchandiseEntity {
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ private String title;
+
+ private BigDecimal price;
+
+ private String brand;
+
+ public MerchandiseEntity() {
+ }
+
+ public MerchandiseEntity(String title, BigDecimal price) {
+ this.title = title;
+ this.price = price;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public BigDecimal getPrice() {
+ return price;
+ }
+
+ public void setPrice(BigDecimal price) {
+ this.price = price;
+ }
+
+ public String getBrand() {
+ return brand;
+ }
+
+ public void setBrand(String brand) {
+ this.brand = brand;
+ }
+
+ @Override
+ public String toString() {
+ return "MerchandiseEntity{" +
+ "id=" + id +
+ ", title='" + title + '\'' +
+ ", price=" + price +
+ ", brand='" + brand + '\'' +
+ '}';
+ }
+}
diff --git a/spring-data-jpa/src/main/resources/ddd.properties b/spring-data-jpa/src/main/resources/ddd.properties
new file mode 100644
index 0000000000..e5126b694b
--- /dev/null
+++ b/spring-data-jpa/src/main/resources/ddd.properties
@@ -0,0 +1 @@
+spring.datasource.initialization-mode=never
\ No newline at end of file
diff --git a/spring-data-jpa/src/main/resources/persistence-multiple-db.properties b/spring-data-jpa/src/main/resources/persistence-multiple-db.properties
index 53c6cecf8b..75534e8a54 100644
--- a/spring-data-jpa/src/main/resources/persistence-multiple-db.properties
+++ b/spring-data-jpa/src/main/resources/persistence-multiple-db.properties
@@ -3,7 +3,7 @@ jdbc.driverClassName=org.h2.Driver
user.jdbc.url=jdbc:h2:mem:spring_jpa_user;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS USERS
product.jdbc.url=jdbc:h2:mem:spring_jpa_product;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS PRODUCTS
jdbc.user=sa
-jdbc.pass=
+jdbc.pass=sa
# hibernate.X
hibernate.dialect=org.hibernate.dialect.H2Dialect
diff --git a/spring-data-jpa/src/main/resources/persistence.properties b/spring-data-jpa/src/main/resources/persistence.properties
index 5e83653401..3543e1b52b 100644
--- a/spring-data-jpa/src/main/resources/persistence.properties
+++ b/spring-data-jpa/src/main/resources/persistence.properties
@@ -2,7 +2,7 @@
jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS USERS
jdbc.user=sa
-jdbc.pass=
+jdbc.pass=sa
# hibernate.X
hibernate.dialect=org.hibernate.dialect.H2Dialect
diff --git a/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/InventoryRepositoryIntegrationTest.java b/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/InventoryRepositoryIntegrationTest.java
new file mode 100644
index 0000000000..9d6334445c
--- /dev/null
+++ b/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/InventoryRepositoryIntegrationTest.java
@@ -0,0 +1,60 @@
+package com.baeldung.dao.repositories;
+
+import com.baeldung.config.PersistenceConfiguration;
+import com.baeldung.domain.MerchandiseEntity;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.math.BigDecimal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+
+@RunWith(SpringRunner.class)
+@DataJpaTest(excludeAutoConfiguration = {PersistenceConfiguration.class})
+public class InventoryRepositoryIntegrationTest {
+
+ private static final String ORIGINAL_TITLE = "Pair of Pants";
+ private static final String UPDATED_TITLE = "Branded Luxury Pants";
+ private static final String UPDATED_BRAND = "Armani";
+ private static final String ORIGINAL_SHORTS_TITLE = "Pair of Shorts";
+
+ @Autowired
+ private InventoryRepository repository;
+
+ @Test
+ public void shouldCreateNewEntryInDB() {
+ MerchandiseEntity pants = new MerchandiseEntity(ORIGINAL_TITLE, BigDecimal.ONE);
+ pants = repository.save(pants);
+
+ MerchandiseEntity shorts = new MerchandiseEntity(ORIGINAL_SHORTS_TITLE, new BigDecimal(3));
+ shorts = repository.save(shorts);
+
+ assertNotNull(pants.getId());
+ assertNotNull(shorts.getId());
+ assertNotEquals(pants.getId(), shorts.getId());
+ }
+
+ @Test
+ public void shouldUpdateExistingEntryInDB() {
+ MerchandiseEntity pants = new MerchandiseEntity(ORIGINAL_TITLE, BigDecimal.ONE);
+ pants = repository.save(pants);
+
+ Long originalId = pants.getId();
+
+ pants.setTitle(UPDATED_TITLE);
+ pants.setPrice(BigDecimal.TEN);
+ pants.setBrand(UPDATED_BRAND);
+
+ MerchandiseEntity result = repository.save(pants);
+
+ assertEquals(originalId, result.getId());
+ assertEquals(UPDATED_TITLE, result.getTitle());
+ assertEquals(BigDecimal.TEN, result.getPrice());
+ assertEquals(UPDATED_BRAND, result.getBrand());
+ }
+}
diff --git a/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/JpaRepositoriesIntegrationTest.java b/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/JpaRepositoriesIntegrationTest.java
index eaadb9e44a..01405c0b8a 100644
--- a/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/JpaRepositoriesIntegrationTest.java
+++ b/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/JpaRepositoriesIntegrationTest.java
@@ -9,28 +9,22 @@ import static junit.framework.TestCase.assertTrue;
import java.util.List;
import java.util.Optional;
-import com.baeldung.config.PersistenceConfiguration;
-import com.baeldung.config.PersistenceProductConfiguration;
-import com.baeldung.config.PersistenceUserConfiguration;
-import com.baeldung.dao.repositories.ItemTypeRepository;
-import com.baeldung.dao.repositories.LocationRepository;
-import com.baeldung.dao.repositories.ReadOnlyLocationRepository;
-import com.baeldung.dao.repositories.StoreRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
+import com.baeldung.config.PersistenceConfiguration;
+import com.baeldung.config.PersistenceProductConfiguration;
+import com.baeldung.config.PersistenceUserConfiguration;
import com.baeldung.domain.Item;
import com.baeldung.domain.ItemType;
import com.baeldung.domain.Location;
import com.baeldung.domain.Store;
@RunWith(SpringRunner.class)
-@DataJpaTest(excludeAutoConfiguration = {PersistenceConfiguration.class, PersistenceUserConfiguration.class, PersistenceProductConfiguration.class})
+@DataJpaTest(excludeAutoConfiguration = { PersistenceConfiguration.class, PersistenceUserConfiguration.class, PersistenceProductConfiguration.class })
public class JpaRepositoriesIntegrationTest {
@Autowired
private LocationRepository locationRepository;
diff --git a/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate2EventsIntegrationTest.java b/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate2EventsIntegrationTest.java
new file mode 100644
index 0000000000..3f650d4d63
--- /dev/null
+++ b/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate2EventsIntegrationTest.java
@@ -0,0 +1,68 @@
+/**
+ *
+ */
+package com.baeldung.ddd.event;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+
+@SpringJUnitConfig
+@SpringBootTest
+class Aggregate2EventsIntegrationTest {
+ @MockBean
+ private TestEventHandler eventHandler;
+ @Autowired
+ private Aggregate2Repository repository;
+
+ // @formatter:off
+ @DisplayName("given aggregate with @AfterDomainEventPublication,"
+ + " when do domain operation and save twice,"
+ + " then an event is published only for the first time")
+ // @formatter:on
+ @Test
+ void afterDomainEvents() {
+ // given
+ Aggregate2 aggregate = new Aggregate2();
+
+ // when
+ aggregate.domainOperation();
+ repository.save(aggregate);
+ repository.save(aggregate);
+
+ // then
+ verify(eventHandler, times(1)).handleEvent(any(DomainEvent.class));
+ }
+
+ @BeforeEach
+ void beforeEach() {
+ repository.deleteAll();
+ }
+
+ // @formatter:off
+ @DisplayName("given aggregate with @DomainEvents,"
+ + " when do domain operation and save,"
+ + " then an event is published")
+ // @formatter:on
+ @Test
+ void domainEvents() {
+ // given
+ Aggregate2 aggregate = new Aggregate2();
+
+ // when
+ aggregate.domainOperation();
+ repository.save(aggregate);
+
+ // then
+ verify(eventHandler, times(1)).handleEvent(any(DomainEvent.class));
+ }
+
+}
diff --git a/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate3EventsIntegrationTest.java b/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate3EventsIntegrationTest.java
new file mode 100644
index 0000000000..893dcac3f8
--- /dev/null
+++ b/spring-data-jpa/src/test/java/com/baeldung/ddd/event/Aggregate3EventsIntegrationTest.java
@@ -0,0 +1,63 @@
+/**
+ *
+ */
+package com.baeldung.ddd.event;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+
+@SpringJUnitConfig
+@SpringBootTest
+class Aggregate3EventsIntegrationTest {
+
+ @MockBean
+ private TestEventHandler eventHandler;
+ @Autowired
+ private Aggregate3Repository repository;
+
+ // @formatter:off
+ @DisplayName("given aggregate extending AbstractAggregateRoot,"
+ + " when do domain operation and save twice,"
+ + " then an event is published only for the first time")
+ // @formatter:on
+ @Test
+ void afterDomainEvents() {
+ // given
+ Aggregate3 aggregate = new Aggregate3();
+
+ // when
+ aggregate.domainOperation();
+ repository.save(aggregate);
+ repository.save(aggregate);
+
+ // then
+ verify(eventHandler, times(1)).handleEvent(any(DomainEvent.class));
+ }
+
+ // @formatter:off
+ @DisplayName("given aggregate extending AbstractAggregateRoot,"
+ + " when do domain operation and save,"
+ + " then an event is published")
+ // @formatter:on
+ @Test
+ void domainEvents() {
+ // given
+ Aggregate3 aggregate = new Aggregate3();
+
+ // when
+ aggregate.domainOperation();
+ repository.save(aggregate);
+
+ // then
+ verify(eventHandler, times(1)).handleEvent(any(DomainEvent.class));
+ }
+
+}
diff --git a/spring-data-jpa/src/test/java/com/baeldung/ddd/event/AggregateEventsIntegrationTest.java b/spring-data-jpa/src/test/java/com/baeldung/ddd/event/AggregateEventsIntegrationTest.java
new file mode 100644
index 0000000000..f0e1147245
--- /dev/null
+++ b/spring-data-jpa/src/test/java/com/baeldung/ddd/event/AggregateEventsIntegrationTest.java
@@ -0,0 +1,82 @@
+package com.baeldung.ddd.event;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.annotation.Bean;
+import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
+
+@SpringJUnitConfig
+@SpringBootTest
+class AggregateEventsIntegrationTest {
+
+ @Autowired
+ private DomainService domainService;
+
+ @MockBean
+ private TestEventHandler eventHandler;
+ @Autowired
+ private ApplicationEventPublisher eventPublisher;
+ @Autowired
+ private AggregateRepository repository;
+
+ // @formatter:off
+ @DisplayName("given existing aggregate,"
+ + " when do domain operation directly on aggregate,"
+ + " then domain event is NOT published")
+ // @formatter:on
+ @Test
+ void aggregateEventsTest() {
+ Aggregate existingDomainEntity = new Aggregate(0, eventPublisher);
+ repository.save(existingDomainEntity);
+
+ // when
+ repository.findById(existingDomainEntity.getId())
+ .get()
+ .domainOperation();
+
+ // then
+ verifyZeroInteractions(eventHandler);
+ }
+
+ @BeforeEach
+ void beforeEach() {
+ repository.deleteAll();
+ }
+
+ // @formatter:off
+ @DisplayName("given existing aggregate,"
+ + " when do domain operation on service,"
+ + " then domain event is published")
+ // @formatter:on
+ @Test
+ void serviceEventsTest() {
+ Aggregate existingDomainEntity = new Aggregate(1, eventPublisher);
+ repository.save(existingDomainEntity);
+
+ // when
+ domainService.serviceDomainOperation(existingDomainEntity.getId());
+
+ // then
+ verify(eventHandler, times(1)).handleEvent(any(DomainEvent.class));
+ }
+
+ @TestConfiguration
+ public static class TestConfig {
+ @Bean
+ public DomainService domainService(AggregateRepository repository, ApplicationEventPublisher eventPublisher) {
+ return new DomainService(repository, eventPublisher);
+ }
+ }
+
+}
diff --git a/spring-data-jpa/src/test/java/com/baeldung/ddd/event/TestEventHandler.java b/spring-data-jpa/src/test/java/com/baeldung/ddd/event/TestEventHandler.java
new file mode 100644
index 0000000000..721402c17a
--- /dev/null
+++ b/spring-data-jpa/src/test/java/com/baeldung/ddd/event/TestEventHandler.java
@@ -0,0 +1,12 @@
+/**
+ *
+ */
+package com.baeldung.ddd.event;
+
+import org.springframework.transaction.event.TransactionalEventListener;
+
+interface TestEventHandler {
+ @TransactionalEventListener
+ void handleEvent(DomainEvent event);
+
+}
diff --git a/spring-data-jpa/src/test/java/com/baeldung/services/JpaMultipleDBIntegrationTest.java b/spring-data-jpa/src/test/java/com/baeldung/services/JpaMultipleDBIntegrationTest.java
index 29b96ae597..71a3fb0b44 100644
--- a/spring-data-jpa/src/test/java/com/baeldung/services/JpaMultipleDBIntegrationTest.java
+++ b/spring-data-jpa/src/test/java/com/baeldung/services/JpaMultipleDBIntegrationTest.java
@@ -1,31 +1,33 @@
package com.baeldung.services;
-import com.baeldung.config.PersistenceProductConfiguration;
-import com.baeldung.config.PersistenceUserConfiguration;
-import com.baeldung.dao.repositories.user.PossessionRepository;
-import com.baeldung.dao.repositories.product.ProductRepository;
-import com.baeldung.dao.repositories.user.UserRepository;
-import com.baeldung.domain.user.Possession;
-import com.baeldung.domain.product.Product;
-import com.baeldung.domain.user.User;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Collections;
+import java.util.Optional;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;
-import java.util.Collections;
-import java.util.Optional;
-
-import static org.junit.Assert.*;
+import com.baeldung.config.PersistenceProductConfiguration;
+import com.baeldung.config.PersistenceUserConfiguration;
+import com.baeldung.dao.repositories.product.ProductRepository;
+import com.baeldung.dao.repositories.user.PossessionRepository;
+import com.baeldung.dao.repositories.user.UserRepository;
+import com.baeldung.domain.product.Product;
+import com.baeldung.domain.user.Possession;
+import com.baeldung.domain.user.User;
@RunWith(SpringRunner.class)
-@ContextConfiguration(classes = {PersistenceUserConfiguration.class, PersistenceProductConfiguration.class})
+@ContextConfiguration(classes = { PersistenceUserConfiguration.class, PersistenceProductConfiguration.class })
@EnableTransactionManagement
@DirtiesContext
public class JpaMultipleDBIntegrationTest {
diff --git a/spring-data-jpa/src/test/java/com/baeldung/services/SpringDataJPABarAuditIntegrationTest.java b/spring-data-jpa/src/test/java/com/baeldung/services/SpringDataJPABarAuditIntegrationTest.java
index 3c36f43192..f3b857c73d 100644
--- a/spring-data-jpa/src/test/java/com/baeldung/services/SpringDataJPABarAuditIntegrationTest.java
+++ b/spring-data-jpa/src/test/java/com/baeldung/services/SpringDataJPABarAuditIntegrationTest.java
@@ -1,8 +1,16 @@
package com.baeldung.services;
-import com.baeldung.config.PersistenceConfiguration;
-import com.baeldung.domain.Bar;
-import org.junit.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -10,15 +18,11 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import com.baeldung.config.PersistenceConfiguration;
+import com.baeldung.domain.Bar;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = { PersistenceConfiguration.class }, loader = AnnotationConfigContextLoader.class)
diff --git a/spring-mvc-java/README.md b/spring-mvc-java/README.md
index c4a0e3579c..44b1d65bc8 100644
--- a/spring-mvc-java/README.md
+++ b/spring-mvc-java/README.md
@@ -28,10 +28,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [The Spring @Controller and @RestController Annotations](http://www.baeldung.com/spring-controller-vs-restcontroller)
- [Spring MVC @PathVariable with a dot (.) gets truncated](http://www.baeldung.com/spring-mvc-pathvariable-dot)
- [A Quick Example of Spring Websockets’ @SendToUser Annotation](http://www.baeldung.com/spring-websockets-sendtouser)
-- [Spring Boot Annotations](http://www.baeldung.com/spring-boot-annotations)
-- [Spring Scheduling Annotations](http://www.baeldung.com/spring-scheduling-annotations)
-- [Spring Web Annotations](http://www.baeldung.com/spring-mvc-annotations)
-- [Spring Core Annotations](http://www.baeldung.com/spring-core-annotations)
- [Using Spring ResponseEntity to Manipulate the HTTP Response](http://www.baeldung.com/spring-response-entity)
- [Using Spring @ResponseStatus to Set HTTP Status Code](http://www.baeldung.com/spring-response-status)
-- [Display RSS Feed with Spring MVC](http://www.baeldung.com/spring-mvc-rss-feed)
diff --git a/spring-mvc-java/pom.xml b/spring-mvc-java/pom.xml
index 83f2556fe0..9d3e0ca1b2 100644
--- a/spring-mvc-java/pom.xml
+++ b/spring-mvc-java/pom.xml
@@ -5,70 +5,54 @@
spring-mvc-java
0.1-SNAPSHOT
spring-mvc-java
+ war
- parent-boot-2
+ parent-spring-5
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-2
+ ../parent-spring-5
-
-
- org.springframework.boot
- spring-boot-starter-thymeleaf
+
+ org.springframework
+ spring-webmvc
+ ${spring.version}
-
- org.springframework.boot
- spring-boot-starter-actuator
-
-
- org.springframework.boot
- spring-boot-devtools
-
-
- org.springframework.boot
- spring-boot-test
- test
-
-
- org.springframework.boot
- spring-boot-starter-aop
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter-websocket
-
-
-
-
- com.fasterxml.jackson.core
- jackson-databind
-
-
-
javax.servlet
javax.servlet-api
+ 4.0.1
+
+
+ javax.servlet.jsp
+ javax.servlet.jsp-api
+ 2.3.3
javax.servlet
jstl
+ ${jstl.version}
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson-databind.version}
org.aspectj
aspectjrt
+ 1.9.1
org.aspectj
aspectjweaver
+ 1.9.1
@@ -80,6 +64,7 @@
net.sourceforge.htmlunit
htmlunit
+ 2.32
commons-logging
@@ -104,10 +89,12 @@
com.jayway.jsonpath
json-path
test
+ 2.4.0
org.springframework
spring-test
+ ${spring.version}
test
@@ -120,34 +107,29 @@
- org.hibernate
+ org.hibernate.validator
hibernate-validator
${hibernate-validator.version}
-
- javax.el
- javax.el-api
- ${javax.el.version}
-
-
- org.glassfish.web
- javax.el
- ${javax.el.version}
-
com.google.code.gson
gson
+ 2.8.5
-
-
-
- com.rometools
- rome
- ${rome.version}
-
+
+ org.springframework
+ spring-websocket
+ ${spring.version}
+
+
+
+ org.springframework
+ spring-messaging
+ ${spring.version}
+
@@ -169,6 +151,7 @@
org.apache.maven.plugins
maven-war-plugin
+ ${maven-war-plugin.version}
false
@@ -262,7 +245,7 @@
3.0.9.RELEASE
- 5.2.5.Final
+ 6.0.10.Final
5.1.40
@@ -281,24 +264,19 @@
2.23
- 2.6
+ 3.2.2
2.7
1.6.1
3.1.0
- 1.8.9
+ 1.9.1
3.16-beta1
-
- 1.10.0
-
- 2.2.4
+ 3.0.1-b06
-
- com.baeldung.app.Application
diff --git a/spring-mvc-java/src/main/java/com/baeldung/app/Application.java b/spring-mvc-java/src/main/java/com/baeldung/app/Application.java
deleted file mode 100644
index 68d078de78..0000000000
--- a/spring-mvc-java/src/main/java/com/baeldung/app/Application.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.baeldung.app;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
-import org.springframework.context.annotation.ComponentScan;
-
-@EnableAutoConfiguration
-@ComponentScan(value = {"com.baeldung.web.controller"}, resourcePattern = "**/FileUploadController.class")
-@SpringBootApplication
-public class Application extends SpringBootServletInitializer {
-
- public static void main(final String[] args) {
- SpringApplication.run(Application.class, args);
- }
-}
\ No newline at end of file
diff --git a/spring-mvc-java/src/main/java/com/baeldung/config/AppInitializer.java b/spring-mvc-java/src/main/java/com/baeldung/config/AppInitializer.java
index 9cf6e384f1..eec12f466f 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/config/AppInitializer.java
+++ b/spring-mvc-java/src/main/java/com/baeldung/config/AppInitializer.java
@@ -14,13 +14,20 @@ public class AppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
- context.setConfigLocation("org.baeldung.config");
+
+ context.scan("com.baeldung");
container.addListener(new ContextLoaderListener(context));
- ServletRegistration.Dynamic dispatcher = container.addServlet("java-servlet", new DispatcherServlet(context));
+ ServletRegistration.Dynamic dispatcher = container.addServlet("mvc", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
- dispatcher.addMapping("/java-servlet/*");
+ dispatcher.addMapping("/");
+
+ // final MultipartConfigElement multipartConfigElement = new
+ // MultipartConfigElement(TMP_FOLDER, MAX_UPLOAD_SIZE,
+ // MAX_UPLOAD_SIZE * 2, MAX_UPLOAD_SIZE / 2);
+ //
+ // appServlet.setMultipartConfig(multipartConfigElement);
}
}
diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ApplicationConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ApplicationConfig.java
deleted file mode 100644
index 261d5793dc..0000000000
--- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ApplicationConfig.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.baeldung.spring.web.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.servlet.ViewResolver;
-import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
-import org.springframework.web.servlet.view.InternalResourceViewResolver;
-import org.springframework.web.servlet.view.JstlView;
-
-@EnableWebMvc
-@Configuration
-@ComponentScan(basePackages = { "com.baeldung.web.controller" })
-public class ApplicationConfig extends WebMvcConfigurerAdapter {
-
- public ApplicationConfig() {
- super();
- }
-
- @Override
- public void addViewControllers(final ViewControllerRegistry registry) {
- super.addViewControllers(registry);
- registry.addViewController("/").setViewName("index");
- }
-
- @Bean
- public ViewResolver viewResolver() {
- final InternalResourceViewResolver bean = new InternalResourceViewResolver();
- bean.setViewClass(JstlView.class);
- bean.setPrefix("/WEB-INF/jsp/");
- bean.setSuffix(".jsp");
- return bean;
- }
-}
\ No newline at end of file
diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ClientWebConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ClientWebConfig.java
deleted file mode 100644
index de47f9f69e..0000000000
--- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ClientWebConfig.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package com.baeldung.spring.web.config;
-
-import javax.servlet.ServletContext;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.MessageSource;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Description;
-import org.springframework.context.support.ResourceBundleMessageSource;
-import org.springframework.web.servlet.ViewResolver;
-import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
-import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-import org.springframework.web.servlet.view.InternalResourceViewResolver;
-import org.springframework.web.servlet.view.JstlView;
-import org.thymeleaf.spring4.SpringTemplateEngine;
-import org.thymeleaf.spring4.view.ThymeleafViewResolver;
-import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
-
-@EnableWebMvc
-@Configuration
-public class ClientWebConfig implements WebMvcConfigurer {
-
- public ClientWebConfig() {
- super();
- }
-
- // API
-
- @Autowired
- private ServletContext ctx;
-
- @Override
- public void addViewControllers(final ViewControllerRegistry registry) {
-
- registry.addViewController("/sample.html");
- }
-
- @Bean
- public ViewResolver thymeleafViewResolver() {
- final ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
- viewResolver.setTemplateEngine(templateEngine());
- viewResolver.setOrder(1);
- return viewResolver;
- }
-
- @Bean
- public ViewResolver viewResolver() {
- final InternalResourceViewResolver bean = new InternalResourceViewResolver();
- bean.setViewClass(JstlView.class);
- bean.setPrefix("/WEB-INF/view/");
- bean.setSuffix(".jsp");
- bean.setOrder(0);
- return bean;
- }
-
- @Bean
- @Description("Thymeleaf template resolver serving HTML 5")
- public ServletContextTemplateResolver templateResolver() {
- final ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(ctx);
- templateResolver.setPrefix("/WEB-INF/templates/");
- templateResolver.setSuffix(".html");
- templateResolver.setTemplateMode("HTML5");
- return templateResolver;
- }
-
- @Bean
- @Description("Thymeleaf template engine with Spring integration")
- public SpringTemplateEngine templateEngine() {
- final SpringTemplateEngine templateEngine = new SpringTemplateEngine();
- templateEngine.setTemplateResolver(templateResolver());
- return templateEngine;
- }
-
- @Bean
- @Description("Spring message resolver")
- public MessageSource messageSource() {
- final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
- messageSource.setBasename("messages");
- return messageSource;
- }
-
- @Override
- public void addResourceHandlers(final ResourceHandlerRegistry registry) {
- registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
- }
-
-}
\ No newline at end of file
diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ContentManagementWebConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ContentManagementWebConfig.java
deleted file mode 100644
index 498105ded1..0000000000
--- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ContentManagementWebConfig.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.baeldung.spring.web.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.http.MediaType;
-import org.springframework.web.servlet.ViewResolver;
-import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
-import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
-import org.springframework.web.servlet.view.InternalResourceViewResolver;
-import org.springframework.web.servlet.view.JstlView;
-
-@EnableWebMvc
-@Configuration
-public class ContentManagementWebConfig extends WebMvcConfigurerAdapter {
-
- public ContentManagementWebConfig() {
- super();
- }
-
- // API
-
- @Override
- public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
- configurer.favorPathExtension(false).favorParameter(true).parameterName("mediaType").ignoreAcceptHeader(true).useJaf(false).defaultContentType(MediaType.APPLICATION_JSON).mediaType("xml", MediaType.APPLICATION_XML).mediaType("json",
- MediaType.APPLICATION_JSON);
- }
-
- @Override
- public void addViewControllers(final ViewControllerRegistry registry) {
- super.addViewControllers(registry);
- registry.addViewController("/sample.html");
- }
-
- @Bean
- public ViewResolver viewResolver() {
- final InternalResourceViewResolver bean = new InternalResourceViewResolver();
- bean.setViewClass(JstlView.class);
- bean.setPrefix("/WEB-INF/view/");
- bean.setSuffix(".jsp");
- bean.setOrder(0);
- return bean;
- }
-
-}
diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java
deleted file mode 100644
index 80ce22edd6..0000000000
--- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.baeldung.spring.web.config;
-
-import org.springframework.web.WebApplicationInitializer;
-import org.springframework.web.context.ContextLoaderListener;
-import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
-import org.springframework.web.context.support.GenericWebApplicationContext;
-import org.springframework.web.servlet.DispatcherServlet;
-
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRegistration;
-import java.util.Set;
-
-public class MainWebAppInitializer implements WebApplicationInitializer {
-
- private static final String TMP_FOLDER = "/tmp";
- private static final int MAX_UPLOAD_SIZE = 5 * 1024 * 1024; // 5 MB
-
- /**
- * Register and configure all Servlet container components necessary to power the web application.
- */
- @Override
- public void onStartup(final ServletContext sc) throws ServletException {
-
- // Create the 'root' Spring application context
- final AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
- root.scan("com.baeldung.spring.web.config");
- // root.getEnvironment().setDefaultProfiles("embedded");
-
- sc.addListener(new ContextLoaderListener(root));
-
- // Handles requests into the application
- final ServletRegistration.Dynamic appServlet = sc.addServlet("mvc", new DispatcherServlet(new GenericWebApplicationContext()));
- appServlet.setLoadOnStartup(1);
-
- // final MultipartConfigElement multipartConfigElement = new
- // MultipartConfigElement(TMP_FOLDER, MAX_UPLOAD_SIZE,
- // MAX_UPLOAD_SIZE * 2, MAX_UPLOAD_SIZE / 2);
- //
- // appServlet.setMultipartConfig(multipartConfigElement);
-
- final Set mappingConflicts = appServlet.addMapping("/");
- if (!mappingConflicts.isEmpty()) {
- throw new IllegalStateException("'appServlet' could not be mapped to '/' due " + "to an existing mapping. This is a known issue under Tomcat versions " + "<= 7.0.14; see https://issues.apache.org/bugzilla/show_bug.cgi?id=51278");
- }
- }
-
-}
diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java
index 11be08a79d..191d721dfb 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java
+++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java
@@ -3,40 +3,105 @@ package com.baeldung.spring.web.config;
import java.util.ArrayList;
import java.util.List;
+import javax.servlet.ServletContext;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Description;
+import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.MediaType;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ViewResolver;
+import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.ResourceBundleViewResolver;
import org.springframework.web.servlet.view.XmlViewResolver;
import org.springframework.web.util.UrlPathHelper;
-import com.baeldung.excel.*;
+import org.thymeleaf.spring4.SpringTemplateEngine;
+import org.thymeleaf.spring4.view.ThymeleafViewResolver;
+import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
+
+import com.baeldung.excel.ExcelPOIHelper;
-@Configuration
@EnableWebMvc
-@ComponentScan("com.baeldung.web")
-public class WebConfig extends WebMvcConfigurerAdapter {
+@Configuration
+@ComponentScan(basePackages = { "com.baeldung.web.controller" })
+public class WebConfig implements WebMvcConfigurer {
- public WebConfig() {
- super();
+ @Autowired
+ private ServletContext ctx;
+
+ @Override
+ public void addViewControllers(final ViewControllerRegistry registry) {
+ registry.addViewController("/").setViewName("index");
+ }
+
+ @Bean
+ public ViewResolver thymeleafViewResolver() {
+ final ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
+ viewResolver.setTemplateEngine(templateEngine());
+ viewResolver.setOrder(1);
+ return viewResolver;
}
- // @Bean
- // public StandardServletMultipartResolver multipartResolver() {
- // return new StandardServletMultipartResolver();
- // }
+ @Bean
+ public ViewResolver viewResolver() {
+ final InternalResourceViewResolver bean = new InternalResourceViewResolver();
+ bean.setViewClass(JstlView.class);
+ bean.setPrefix("/WEB-INF/view/");
+ bean.setSuffix(".jsp");
+ bean.setOrder(0);
+ return bean;
+ }
+ @Bean
+ @Description("Thymeleaf template resolver serving HTML 5")
+ public ServletContextTemplateResolver templateResolver() {
+ final ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(ctx);
+ templateResolver.setPrefix("/WEB-INF/templates/");
+ templateResolver.setSuffix(".html");
+ templateResolver.setTemplateMode("HTML5");
+ return templateResolver;
+ }
+
+ @Bean
+ @Description("Thymeleaf template engine with Spring integration")
+ public SpringTemplateEngine templateEngine() {
+ final SpringTemplateEngine templateEngine = new SpringTemplateEngine();
+ templateEngine.setTemplateResolver(templateResolver());
+ return templateEngine;
+ }
+
+ @Bean
+ @Description("Spring message resolver")
+ public MessageSource messageSource() {
+ final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
+ messageSource.setBasename("messages");
+ return messageSource;
+ }
+
+ @Override
+ public void addResourceHandlers(final ResourceHandlerRegistry registry) {
+ registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
+ }
+
+ @Override
+ public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
+ configurer.favorPathExtension(false).favorParameter(true).parameterName("mediaType").ignoreAcceptHeader(true).useRegisteredExtensionsOnly(false).defaultContentType(MediaType.APPLICATION_JSON).mediaType("xml", MediaType.APPLICATION_XML).mediaType("json",
+ MediaType.APPLICATION_JSON);
+ }
@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
@@ -45,23 +110,7 @@ public class WebConfig extends WebMvcConfigurerAdapter {
return multipartResolver;
}
-
- @Override
- public void addViewControllers(final ViewControllerRegistry registry) {
- super.addViewControllers(registry);
- registry.addViewController("/sample.html");
- }
-
- @Bean
- public ViewResolver internalResourceViewResolver() {
- final InternalResourceViewResolver bean = new InternalResourceViewResolver();
- bean.setViewClass(JstlView.class);
- bean.setPrefix("/WEB-INF/view/");
- bean.setSuffix(".jsp");
- bean.setOrder(2);
- return bean;
- }
-
+
@Bean
public ViewResolver xmlViewResolver() {
final XmlViewResolver bean = new XmlViewResolver();
@@ -112,5 +161,4 @@ public class WebConfig extends WebMvcConfigurerAdapter {
public ExcelPOIHelper excelPOIHelper() {
return new ExcelPOIHelper();
}
-
-}
+}
\ No newline at end of file
diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketConfig.java
index 93ec13da58..0793658e90 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketConfig.java
+++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketConfig.java
@@ -2,13 +2,13 @@ package com.baeldung.spring.web.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
-import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
+import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@Configuration
@EnableWebSocketMessageBroker
-public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
+public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(final MessageBrokerRegistry config) {
diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketSendToUserConfig.java b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketSendToUserConfig.java
index 7f14380e5e..dbd52e20ba 100644
--- a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketSendToUserConfig.java
+++ b/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebSocketSendToUserConfig.java
@@ -6,9 +6,9 @@ import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.WebSocketHandler;
-import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
+import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
import javax.servlet.http.HttpSession;
@@ -16,7 +16,7 @@ import java.util.Map;
@Configuration
@EnableWebSocketMessageBroker
-public class WebSocketSendToUserConfig extends AbstractWebSocketMessageBrokerConfigurer {
+public class WebSocketSendToUserConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/SampleController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/SampleController.java
new file mode 100644
index 0000000000..c13986e005
--- /dev/null
+++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/SampleController.java
@@ -0,0 +1,13 @@
+package com.baeldung.web.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@Controller
+public class SampleController {
+ @GetMapping("/sample")
+ public String showForm() {
+ return "sample";
+ }
+
+}
diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java b/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java
index b628228b7e..384bd85ec6 100644
--- a/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java
+++ b/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java
@@ -20,12 +20,12 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
-import com.baeldung.spring.web.config.ApplicationConfig;
+import com.baeldung.spring.web.config.WebConfig;
import com.baeldung.spring.web.config.WebConfig;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
-@ContextConfiguration(classes = { ApplicationConfig.class, WebConfig.class })
+@ContextConfiguration(classes = { WebConfig.class, WebConfig.class })
public class GreetControllerIntegrationTest {
@Autowired
diff --git a/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml b/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml
index 0129875f60..0f1cfa27ac 100644
--- a/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml
+++ b/spring-swagger-codegen/spring-swagger-codegen-api-client/pom.xml
@@ -54,20 +54,6 @@
pertest
-
- maven-dependency-plugin
-
-
- package
-
- copy-dependencies
-
-
- ${project.build.directory}/lib
-
-
-
-
diff --git a/testing-modules/gatling/README.md b/testing-modules/gatling/README.md
index 5c81c4bd6a..941ab75f06 100644
--- a/testing-modules/gatling/README.md
+++ b/testing-modules/gatling/README.md
@@ -1,2 +1,5 @@
### Relevant Articles:
- [Intro to Gatling](http://www.baeldung.com/introduction-to-gatling)
+
+### Running a simualtion
+- To run a simulation use "simulation" profile, command - `mvn install -Psimulation -Dgib.enabled=false`
diff --git a/testing-modules/gatling/pom.xml b/testing-modules/gatling/pom.xml
index 1afaefd47e..8d4c89ec62 100644
--- a/testing-modules/gatling/pom.xml
+++ b/testing-modules/gatling/pom.xml
@@ -7,13 +7,13 @@
gatling
1.0-SNAPSHOT
-
- com.baeldung
- parent-modules
- 1.0.0-SNAPSHOT
- ../../
-
-
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+ ../../
+
+
io.gatling.highcharts
@@ -68,6 +68,14 @@
+
+
+
+
+
+ simulation
+
+
io.gatling
gatling-maven-plugin
@@ -78,11 +86,16 @@
execute
+
+ true
+
+
+
@@ -113,10 +126,10 @@
1.8
1.8
UTF-8
- 2.11.12
- 2.2.5
+ 2.12.6
+ 2.3.1
3.2.2
- 2.2.1
+ 2.2.4
diff --git a/testing-modules/testng/pom.xml b/testing-modules/testng/pom.xml
index 028db38727..a9f680aafb 100644
--- a/testing-modules/testng/pom.xml
+++ b/testing-modules/testng/pom.xml
@@ -38,24 +38,6 @@
true
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- prepare-package
-
- copy-dependencies
-
-
- ${project.build.directory}/libs
-
-
-
-
-