diff --git a/.gitignore b/.gitignore
index 180462a32f..7fe2778755 100644
--- a/.gitignore
+++ b/.gitignore
@@ -62,3 +62,5 @@ jmeter/src/main/resources/*-JMeter.csv
**/dist
**/tmp
**/out-tsc
+**/nbproject/
+**/nb-configuration.xml
\ No newline at end of file
diff --git a/README.md b/README.md
index adb17ca7e5..8e0a5eb9ee 100644
--- a/README.md
+++ b/README.md
@@ -21,3 +21,8 @@ In additional to Spring, the following technologies are in focus: `core Java`, `
Building the project
====================
To do the full build, do: `mvn install -Pdefault -Dgib.enabled=false`
+
+
+Building a single module
+====================
+To build a specific module run the command: `mvn clean install -Dgib.enabled=false` in the module directory
diff --git a/algorithms/src/main/java/com/baeldung/algorithms/insertionsort/InsertionSort.java b/algorithms/src/main/java/com/baeldung/algorithms/insertionsort/InsertionSort.java
new file mode 100644
index 0000000000..02dd485cf1
--- /dev/null
+++ b/algorithms/src/main/java/com/baeldung/algorithms/insertionsort/InsertionSort.java
@@ -0,0 +1,41 @@
+package com.baeldung.algorithms.insertionsort;
+
+public class InsertionSort {
+
+ public static void insertionSortImperative(int[] input) {
+ for (int i = 1; i < input.length; i++) {
+ int key = input[i];
+ int j = i - 1;
+ while (j >= 0 && input[j] > key) {
+ input[j + 1] = input[j];
+ j = j - 1;
+ }
+ input[j + 1] = key;
+ }
+ }
+
+ public static void insertionSortRecursive(int[] input) {
+ insertionSortRecursive(input, input.length);
+ }
+
+ private static void insertionSortRecursive(int[] input, int i) {
+ // base case
+ if (i <= 1) {
+ return;
+ }
+
+ // sort the first i - 1 elements of the array
+ insertionSortRecursive(input, i - 1);
+
+ // then find the correct position of the element at position i
+ int key = input[i - 1];
+ int j = i - 2;
+ // shifting the elements from their position by 1
+ while (j >= 0 && input[j] > key) {
+ input[j + 1] = input[j];
+ j = j - 1;
+ }
+ // inserting the key at the appropriate position
+ input[j + 1] = key;
+ }
+}
diff --git a/algorithms/src/test/java/com/baeldung/algorithms/insertionsort/InsertionSortUnitTest.java b/algorithms/src/test/java/com/baeldung/algorithms/insertionsort/InsertionSortUnitTest.java
new file mode 100644
index 0000000000..b3d7e8c534
--- /dev/null
+++ b/algorithms/src/test/java/com/baeldung/algorithms/insertionsort/InsertionSortUnitTest.java
@@ -0,0 +1,25 @@
+package com.baeldung.algorithms.insertionsort;
+
+import com.baeldung.algorithms.insertionsort.InsertionSort;
+import org.junit.Test;
+
+import static org.junit.Assert.assertArrayEquals;
+
+public class InsertionSortUnitTest {
+
+ @Test
+ public void givenUnsortedArray_whenInsertionSortImperative_thenSortedAsc() {
+ int[] input = {6, 2, 3, 4, 5, 1};
+ InsertionSort.insertionSortImperative(input);
+ int[] expected = {1, 2, 3, 4, 5, 6};
+ assertArrayEquals("the two arrays are not equal", expected, input);
+ }
+
+ @Test
+ public void givenUnsortedArray_whenInsertionSortRecursive_thenSortedAsc() {
+ int[] input = {6, 4, 5, 2, 3, 1};
+ InsertionSort.insertionSortRecursive(input);
+ int[] expected = {1, 2, 3, 4, 5, 6};
+ assertArrayEquals("the two arrays are not equal", expected, input);
+ }
+}
diff --git a/core-java-8/src/test/java/com/baeldung/internationalization/DateTimeFormatterUnitTest.java b/core-java-8/src/test/java/com/baeldung/internationalization/DateTimeFormatterUnitTest.java
deleted file mode 100644
index 4d95bc82e1..0000000000
--- a/core-java-8/src/test/java/com/baeldung/internationalization/DateTimeFormatterUnitTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.baeldung.internationalization;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
-import java.time.format.FormatStyle;
-import java.util.Locale;
-import java.util.TimeZone;
-
-public class DateTimeFormatterUnitTest {
-
- @Test
- public void givenDefaultUsLocaleAndDateTimeAndPattern_whenFormatWithDifferentLocales_thenGettingLocalizedDateTimes() {
- Locale.setDefault(Locale.US);
- LocalDateTime localDateTime = LocalDateTime.of(2018, 1, 1, 10, 15, 50, 500);
- String pattern = "dd-MMMM-yyyy HH:mm:ss.SSS";
-
- DateTimeFormatter defaultTimeFormatter = DateTimeFormatter.ofPattern(pattern);
- DateTimeFormatter plTimeFormatter = DateTimeFormatter.ofPattern(pattern, new Locale("pl", "PL"));
- DateTimeFormatter deTimeFormatter = DateTimeFormatter.ofPattern(pattern).withLocale(Locale.GERMANY);
-
- Assert.assertEquals("01-January-2018 10:15:50.000", defaultTimeFormatter.format(localDateTime));
- Assert.assertEquals("01-stycznia-2018 10:15:50.000", plTimeFormatter.format(localDateTime));
- Assert.assertEquals("01-Januar-2018 10:15:50.000", deTimeFormatter.format(localDateTime));
- }
-
- @Test
- public void givenDateTimeAndTimeZone_whenFormatWithDifferentLocales_thenGettingLocalizedZonedDateTimes() {
- Locale.setDefault(Locale.US);
- LocalDateTime localDateTime = LocalDateTime.of(2018, 1, 1, 10, 15, 50, 500);
- ZoneId losAngelesTimeZone = TimeZone.getTimeZone("America/Los_Angeles").toZoneId();
-
- DateTimeFormatter localizedFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL);
- DateTimeFormatter frLocalizedFormatter =
- DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(Locale.FRANCE);
- String formattedDateTime = localizedFormatter.format(ZonedDateTime.of(localDateTime, losAngelesTimeZone));
- String frFormattedDateTime = frLocalizedFormatter.format(ZonedDateTime.of(localDateTime, losAngelesTimeZone));
-
- Assert.assertEquals("Monday, January 1, 2018 10:15:50 AM PST", formattedDateTime);
- Assert.assertEquals("lundi 1 janvier 2018 10 h 15 PST", frFormattedDateTime);
- }
-}
diff --git a/core-java-collections/README.md b/core-java-collections/README.md
index ca275d7c09..d9d768961c 100644
--- a/core-java-collections/README.md
+++ b/core-java-collections/README.md
@@ -48,6 +48,7 @@
- [Thread Safe LIFO Data Structure Implementations](https://www.baeldung.com/java-lifo-thread-safe)
- [Collections.emptyList() vs. New List Instance](https://www.baeldung.com/java-collections-emptylist-new-list)
- [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap)
+- [Differences Between Collection.clear() and Collection.removeAll()](https://www.baeldung.com/java-collection-clear-vs-removeall)
- [Performance of contains() in a HashSet vs ArrayList](https://www.baeldung.com/java-hashset-arraylist-contains-performance)
- [Get the Key for a Value from a Java Map](https://www.baeldung.com/java-map-key-from-value)
- [Time Complexity of Java Collections](https://www.baeldung.com/java-collections-complexity)
diff --git a/core-java-collections/pom.xml b/core-java-collections/pom.xml
index 06b79fff22..b4a6e26d13 100644
--- a/core-java-collections/pom.xml
+++ b/core-java-collections/pom.xml
@@ -1,90 +1,88 @@
-
- 4.0.0
- com.baeldung
- core-java-collections
- 0.1.0-SNAPSHOT
- jar
- core-java-collections
-
-
- com.baeldung
- parent-java
- 0.0.1-SNAPSHOT
- ../parent-java
-
-
-
-
- net.sourceforge.collections
- collections-generic
- ${collections-generic.version}
-
-
- org.apache.commons
- commons-collections4
- ${commons-collections4.version}
-
-
- com.jayway.awaitility
- awaitility
- ${avaitility.version}
- test
-
-
- org.apache.commons
- commons-lang3
- ${commons-lang3.version}
-
-
- org.eclipse.collections
- eclipse-collections
- ${eclipse.collections.version}
-
-
- org.assertj
- assertj-core
- ${assertj.version}
- test
-
-
- org.junit.platform
- junit-platform-runner
- ${junit.platform.version}
- test
-
-
- org.openjdk.jmh
- jmh-core
- ${openjdk.jmh.version}
-
-
- org.openjdk.jmh
- jmh-generator-annprocess
- ${openjdk.jmh.version}
-
-
- org.apache.commons
- commons-exec
- 1.3
-
-
- one.util
- streamex
- 0.6.5
-
-
-
-
-
-
- 1.19
- 1.2.0
- 3.5
- 4.1
- 4.01
- 1.7.0
- 3.6.1
- 7.1.0
-
-
+
+ 4.0.0
+ core-java-collections
+ 0.1.0-SNAPSHOT
+ jar
+ core-java-collections
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+
+ net.sourceforge.collections
+ collections-generic
+ ${collections-generic.version}
+
+
+ org.apache.commons
+ commons-collections4
+ ${commons-collections4.version}
+
+
+ com.jayway.awaitility
+ awaitility
+ ${avaitility.version}
+ test
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+ org.eclipse.collections
+ eclipse-collections
+ ${eclipse.collections.version}
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+ org.junit.platform
+ junit-platform-runner
+ ${junit.platform.version}
+ test
+
+
+ org.openjdk.jmh
+ jmh-core
+ ${openjdk.jmh.version}
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ ${openjdk.jmh.version}
+
+
+ org.apache.commons
+ commons-exec
+ 1.3
+
+
+
+ one.util
+ streamex
+ 0.6.5
+
+
+
+
+ 1.19
+ 1.2.0
+ 3.5
+ 4.1
+ 4.01
+ 1.7.0
+ 3.6.1
+ 7.1.0
+
+
diff --git a/core-java-collections/src/main/java/com/baeldung/convertcollectiontoarraylist/Foo.java b/core-java-collections/src/main/java/com/baeldung/convertcollectiontoarraylist/Foo.java
new file mode 100644
index 0000000000..5c9464182e
--- /dev/null
+++ b/core-java-collections/src/main/java/com/baeldung/convertcollectiontoarraylist/Foo.java
@@ -0,0 +1,52 @@
+package com.baeldung.convertcollectiontoarraylist;
+
+/**
+ * This POJO is the element type of our collection. It has a deepCopy() method.
+ *
+ * @author chris
+ */
+public class Foo {
+
+ private int id;
+ private String name;
+ private Foo parent;
+
+ public Foo() {
+ }
+
+ public Foo(int id, String name, Foo parent) {
+ this.id = id;
+ this.name = name;
+ this.parent = parent;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Foo getParent() {
+ return parent;
+ }
+
+ public void setParent(Foo parent) {
+ this.parent = parent;
+ }
+
+ public Foo deepCopy() {
+ return new Foo(
+ this.id, this.name, this.parent != null ? this.parent.deepCopy() : null);
+ }
+
+}
diff --git a/core-java-collections/src/main/java/com/baeldung/synchronizedcollections/application/Application.java b/core-java-collections/src/main/java/com/baeldung/synchronizedcollections/application/Application.java
new file mode 100644
index 0000000000..1840c125d0
--- /dev/null
+++ b/core-java-collections/src/main/java/com/baeldung/synchronizedcollections/application/Application.java
@@ -0,0 +1,18 @@
+package com.baeldung.synchronizedcollections.application;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Logger;
+
+public class Application {
+
+ private static final Logger LOGGER = Logger.getLogger(Application.class.getName());
+
+ public static void main(String[] args) throws InterruptedException {
+ List syncCollection = Collections.synchronizedList(Arrays.asList(1, 2, 3, 4, 5, 6));
+ synchronized (syncCollection) {
+ syncCollection.forEach((e) -> {LOGGER.info(e.toString());});
+ }
+ }
+}
diff --git a/core-java-collections/src/test/java/com/baeldung/convertcollectiontoarraylist/FooUnitTest.java b/core-java-collections/src/test/java/com/baeldung/convertcollectiontoarraylist/FooUnitTest.java
new file mode 100644
index 0000000000..5be4121bc7
--- /dev/null
+++ b/core-java-collections/src/test/java/com/baeldung/convertcollectiontoarraylist/FooUnitTest.java
@@ -0,0 +1,148 @@
+package com.baeldung.convertcollectiontoarraylist;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import static java.util.stream.Collectors.toCollection;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author chris
+ */
+public class FooUnitTest {
+ private static Collection srcCollection = new HashSet<>();
+
+ public FooUnitTest() {
+ }
+
+ @BeforeClass
+ public static void setUpClass() {
+ int i = 0;
+ Foo john = new Foo(i++, "John", null);
+ Foo mary = new Foo(i++, "Mary", null);
+ Foo sam = new Foo(i++, "Sam", john);
+ Foo alice = new Foo(i++, "Alice", john);
+ Foo buffy = new Foo(i++, "Buffy", sam);
+ srcCollection.add(john);
+ srcCollection.add(mary);
+ srcCollection.add(sam);
+ srcCollection.add(alice);
+ srcCollection.add(buffy);
+
+ // make sure the collection isn't sorted accidentally
+ assertFalse("Oops: source collection is already sorted!", isSorted(srcCollection));
+ }
+
+ /**
+ * Section 3. Using the ArrayList Constructor
+ */
+ @Test
+ public void whenUsingConstructor_thenVerifyShallowCopy() {
+ ArrayList newList = new ArrayList<>(srcCollection);
+ verifyShallowCopy(srcCollection, newList);
+ }
+
+ /**
+ * Section 4. Using the Streams API
+ */
+ @Test
+ public void whenUsingStream_thenVerifyShallowCopy() {
+ ArrayList newList = srcCollection.stream().collect(toCollection(ArrayList::new));
+
+ verifyShallowCopy(srcCollection, newList);
+ }
+
+ /**
+ * Section 5. Deep Copy
+ */
+ @Test
+ public void whenUsingDeepCopy_thenVerifyDeepCopy() {
+ ArrayList newList = srcCollection.stream()
+ .map(foo -> foo.deepCopy())
+ .collect(toCollection(ArrayList::new));
+
+ verifyDeepCopy(srcCollection, newList);
+ }
+
+ /**
+ * Section 6. Controlling the List Order
+ */
+ @Test
+ public void whenUsingSortedStream_thenVerifySortOrder() {
+ ArrayList newList = srcCollection.stream()
+ .sorted(Comparator.comparing(Foo::getName))
+ .collect(toCollection(ArrayList::new));
+
+ assertTrue("ArrayList is not sorted by name", isSorted(newList));
+ }
+
+ /**
+ * Verify that the contents of the two collections are the same
+ * @param a
+ * @param b
+ */
+ private void verifyShallowCopy(Collection a, Collection b) {
+ assertEquals("Collections have different lengths", a.size(), b.size());
+ Iterator iterA = a.iterator();
+ Iterator iterB = b.iterator();
+ while (iterA.hasNext()) {
+ // use '==' to test instance identity
+ assertTrue("Foo instances differ!", iterA.next() == iterB.next());
+ }
+ }
+
+ /**
+ * Verify that the contents of the two collections are the same
+ * @param a
+ * @param b
+ */
+ private void verifyDeepCopy(Collection a, Collection b) {
+ assertEquals("Collections have different lengths", a.size(), b.size());
+ Iterator iterA = a.iterator();
+ Iterator iterB = b.iterator();
+ while (iterA.hasNext()) {
+ Foo nextA = iterA.next();
+ Foo nextB = iterB.next();
+ // should not be same instance
+ assertFalse("Foo instances are the same!", nextA == nextB);
+ // but should have same content
+ assertFalse("Foo instances have different content!", fooDiff(nextA, nextB));
+ }
+ }
+
+ /**
+ * Return true if the contents of a and b differ. Test parent recursively
+ * @param a
+ * @param b
+ * @return False if the two items are the same
+ */
+ private boolean fooDiff(Foo a, Foo b) {
+ if (a != null && b != null) {
+ return a.getId() != b.getId()
+ || !a.getName().equals(b.getName())
+ || fooDiff(a.getParent(), b.getParent());
+ }
+ return !(a == null && b == null);
+ }
+
+ /**
+ * @param c collection of Foo
+ * @return true if the collection is sorted by name
+ */
+ private static boolean isSorted(Collection c) {
+ String prevName = null;
+ for (Foo foo : c) {
+ if (prevName == null || foo.getName().compareTo(prevName) > 0) {
+ prevName = foo.getName();
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/core-java-collections/src/test/java/com/baeldung/java/map/KeyCheckTest.java b/core-java-collections/src/test/java/com/baeldung/java/map/KeyCheckTest.java
deleted file mode 100644
index 024b2973d2..0000000000
--- a/core-java-collections/src/test/java/com/baeldung/java/map/KeyCheckTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.baeldung.java.map;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.collections4.MultiMap;
-import org.apache.commons.collections4.MultiMapUtils;
-import org.apache.commons.collections4.MultiValuedMap;
-import org.apache.commons.collections4.map.MultiValueMap;
-import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
-import org.apache.commons.collections4.multimap.HashSetValuedHashMap;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.TreeMultimap;
-
-
-public class KeyCheckTest {
-
- @Test
- public void whenKeyIsPresent_thenContainsKeyReturnsTrue() {
- Map map = Collections.singletonMap("key", "value");
-
- assertTrue(map.containsKey("key"));
- assertFalse(map.containsKey("missing"));
- }
-
- @Test
- public void whenKeyHasNullValue_thenGetStillWorks() {
- Map map = Collections.singletonMap("nothing", null);
-
- assertTrue(map.containsKey("nothing"));
- assertNull(map.get("nothing"));
- }
-}
\ No newline at end of file
diff --git a/core-java-collections/src/test/java/com/baeldung/java/map/KeyCheckUnitTest.java b/core-java-collections/src/test/java/com/baeldung/java/map/KeyCheckUnitTest.java
new file mode 100644
index 0000000000..2c97a97690
--- /dev/null
+++ b/core-java-collections/src/test/java/com/baeldung/java/map/KeyCheckUnitTest.java
@@ -0,0 +1,29 @@
+package com.baeldung.java.map;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.junit.Test;
+
+public class KeyCheckUnitTest {
+
+ @Test
+ public void whenKeyIsPresent_thenContainsKeyReturnsTrue() {
+ Map map = Collections.singletonMap("key", "value");
+
+ assertTrue(map.containsKey("key"));
+ assertFalse(map.containsKey("missing"));
+ }
+
+ @Test
+ public void whenKeyHasNullValue_thenGetStillWorks() {
+ Map map = Collections.singletonMap("nothing", null);
+
+ assertTrue(map.containsKey("nothing"));
+ assertNull(map.get("nothing"));
+ }
+}
\ No newline at end of file
diff --git a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedCollectionUnitTest.java b/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedCollectionUnitTest.java
new file mode 100644
index 0000000000..84feeb6eaa
--- /dev/null
+++ b/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedCollectionUnitTest.java
@@ -0,0 +1,28 @@
+package com.baeldung.synchronizedcollections.test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class SynchronizedCollectionUnitTest {
+
+ @Test
+ public void givenSynchronizedCollection_whenTwoThreadsAddElements_thenCorrectCollectionSize() throws InterruptedException {
+ Collection syncCollection = Collections.synchronizedCollection(new ArrayList<>());
+
+ Runnable listOperations = () -> {
+ syncCollection.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));
+ };
+ Thread thread1 = new Thread(listOperations);
+ Thread thread2 = new Thread(listOperations);
+ thread1.start();
+ thread2.start();
+ thread1.join();
+ thread2.join();
+
+ assertThat(syncCollection.size()).isEqualTo(12);
+ }
+}
diff --git a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedListUnitTest.java b/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedListUnitTest.java
new file mode 100644
index 0000000000..68fc3becd4
--- /dev/null
+++ b/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedListUnitTest.java
@@ -0,0 +1,51 @@
+package com.baeldung.synchronizedcollections.test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Test;
+import static org.assertj.core.api.Assertions.*;
+
+public class SynchronizedListUnitTest {
+
+ @Test
+ public void givenSynchronizedList_whenTwoThreadsAddElements_thenCorrectListSize() throws InterruptedException {
+ List syncList = Collections.synchronizedList(new ArrayList<>());
+
+ Runnable listOperations = () -> {
+ syncList.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));
+ };
+ Thread thread1 = new Thread(listOperations);
+ Thread thread2 = new Thread(listOperations);
+ thread1.start();
+ thread2.start();
+ thread1.join();
+ thread2.join();
+
+ assertThat(syncList.size()).isEqualTo(12);
+ }
+
+ @Test
+ public void givenStringList_whenTwoThreadsIterateOnSynchronizedList_thenCorrectResult() throws InterruptedException {
+ List syncCollection = Collections.synchronizedList(Arrays.asList("a", "b", "c"));
+ List uppercasedCollection = new ArrayList<>();
+
+ Runnable listOperations = () -> {
+ synchronized (syncCollection) {
+ syncCollection.forEach((e) -> {
+ uppercasedCollection.add(e.toUpperCase());
+ });
+ }
+ };
+
+ Thread thread1 = new Thread(listOperations);
+ Thread thread2 = new Thread(listOperations);
+ thread1.start();
+ thread2.start();
+ thread1.join();
+ thread2.join();
+
+ assertThat(uppercasedCollection.get(0)).isEqualTo("A");
+ }
+}
diff --git a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedMapUnitTest.java b/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedMapUnitTest.java
new file mode 100644
index 0000000000..abfb866e9c
--- /dev/null
+++ b/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedMapUnitTest.java
@@ -0,0 +1,30 @@
+package com.baeldung.synchronizedcollections.test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Test;
+import static org.assertj.core.api.Assertions.*;
+
+public class SynchronizedMapUnitTest {
+
+ @Test
+ public void givenSynchronizedMap_whenTwoThreadsAddElements_thenCorrectMapSize() throws InterruptedException {
+ Map syncMap = Collections.synchronizedMap(new HashMap<>());
+
+ Runnable mapOperations = () -> {
+ syncMap.put(1, "one");
+ syncMap.put(2, "two");
+ syncMap.put(3, "three");
+
+ };
+ Thread thread1 = new Thread(mapOperations);
+ Thread thread2 = new Thread(mapOperations);
+ thread1.start();
+ thread2.start();
+ thread1.join();
+ thread2.join();
+
+ assertThat(syncMap.size()).isEqualTo(3);
+ }
+}
diff --git a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSetUnitTest.java b/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSetUnitTest.java
new file mode 100644
index 0000000000..58a33b207d
--- /dev/null
+++ b/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSetUnitTest.java
@@ -0,0 +1,26 @@
+package com.baeldung.synchronizedcollections.test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import org.junit.Test;
+import static org.assertj.core.api.Assertions.*;
+
+public class SynchronizedSetUnitTest {
+
+ @Test
+ public void givenSynchronizedSet_whenTwoThreadsAddElements_thenCorrectSetSize() throws InterruptedException {
+ Set syncSet = Collections.synchronizedSet(new HashSet<>());
+
+ Runnable setOperations = () -> {syncSet.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));};
+ Thread thread1 = new Thread(setOperations);
+ Thread thread2 = new Thread(setOperations);
+ thread1.start();
+ thread2.start();
+ thread1.join();
+ thread2.join();
+
+ assertThat(syncSet.size()).isEqualTo(6);
+ }
+}
diff --git a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedMapUnitTest.java b/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedMapUnitTest.java
new file mode 100644
index 0000000000..4b0ed6d8c8
--- /dev/null
+++ b/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedMapUnitTest.java
@@ -0,0 +1,29 @@
+package com.baeldung.synchronizedcollections.test;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.TreeMap;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class SynchronizedSortedMapUnitTest {
+
+ @Test
+ public void givenSynchronizedSorteMap_whenTwoThreadsAddElements_thenCorrectSortedMapSize() throws InterruptedException {
+ Map syncSortedMap = Collections.synchronizedSortedMap(new TreeMap<>());
+
+ Runnable sortedMapOperations = () -> {
+ syncSortedMap.put(1, "One");
+ syncSortedMap.put(2, "Two");
+ syncSortedMap.put(3, "Three");
+ };
+ Thread thread1 = new Thread(sortedMapOperations);
+ Thread thread2 = new Thread(sortedMapOperations);
+ thread1.start();
+ thread2.start();
+ thread1.join();
+ thread2.join();
+
+ assertThat(syncSortedMap.size()).isEqualTo(3);
+ }
+}
diff --git a/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedSetUnitTest.java b/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedSetUnitTest.java
new file mode 100644
index 0000000000..0e26c6eb1c
--- /dev/null
+++ b/core-java-collections/src/test/java/com/baeldung/synchronizedcollections/test/SynchronizedSortedSetUnitTest.java
@@ -0,0 +1,28 @@
+package com.baeldung.synchronizedcollections.test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+
+public class SynchronizedSortedSetUnitTest {
+
+ @Test
+ public void givenSynchronizedSortedSet_whenTwoThreadsAddElements_thenCorrectSortedSetSize() throws InterruptedException {
+ SortedSet syncSortedSet = Collections.synchronizedSortedSet(new TreeSet<>());
+
+ Runnable sortedSetOperations = () -> {syncSortedSet.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));};
+ sortedSetOperations.run();
+ sortedSetOperations.run();
+ Thread thread1 = new Thread(sortedSetOperations);
+ Thread thread2 = new Thread(sortedSetOperations);
+ thread1.start();
+ thread2.start();
+ thread1.join();
+ thread2.join();
+
+ assertThat(syncSortedSet.size()).isEqualTo(6);
+ }
+}
diff --git a/core-java-io/src/main/java/com/baeldung/stream/OutputStreamExamples.java b/core-java-io/src/main/java/com/baeldung/stream/OutputStreamExamples.java
new file mode 100644
index 0000000000..c7168c5b26
--- /dev/null
+++ b/core-java-io/src/main/java/com/baeldung/stream/OutputStreamExamples.java
@@ -0,0 +1,48 @@
+package com.baeldung.stream;
+
+import java.io.BufferedOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+
+public class OutputStreamExamples {
+
+ public void fileOutputStreamByteSequence(String file, String data) throws IOException {
+ byte[] bytes = data.getBytes();
+ try (OutputStream out = new FileOutputStream(file)) {
+ out.write(bytes);
+ }
+ }
+
+ public void fileOutputStreamByteSubSequence(String file, String data) throws IOException {
+ byte[] bytes = data.getBytes();
+ try (OutputStream out = new FileOutputStream(file)) {
+ out.write(bytes, 6, 5);
+ }
+ }
+
+ public void fileOutputStreamByteSingle(String file, String data) throws IOException {
+ byte[] bytes = data.getBytes();
+ try (OutputStream out = new FileOutputStream(file)) {
+ out.write(bytes[6]);
+ }
+ }
+
+ public void bufferedOutputStream(String file, String... data) throws IOException {
+ try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file))) {
+ for (String s : data) {
+ out.write(s.getBytes());
+ out.write(" ".getBytes());
+ }
+ }
+ }
+
+ public void outputStreamWriter(String file, String data) throws IOException {
+ try (OutputStream out = new FileOutputStream(file); Writer writer = new OutputStreamWriter(out, "UTF-8")) {
+ writer.write(data);
+ }
+ }
+
+}
diff --git a/core-java-io/src/test/java/com/baeldung/stream/OutputStreamExamplesUnitTest.java b/core-java-io/src/test/java/com/baeldung/stream/OutputStreamExamplesUnitTest.java
new file mode 100644
index 0000000000..aa949259a0
--- /dev/null
+++ b/core-java-io/src/test/java/com/baeldung/stream/OutputStreamExamplesUnitTest.java
@@ -0,0 +1,76 @@
+package com.baeldung.stream;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class OutputStreamExamplesUnitTest {
+
+ StringBuilder filePath = new StringBuilder();
+
+ @Before
+ public void init() {
+ filePath.append("src");
+ filePath.append(File.separator);
+ filePath.append("test");
+ filePath.append(File.separator);
+ filePath.append("resources");
+ filePath.append(File.separator);
+ filePath.append("output_file.txt");
+ }
+
+ @Test
+ public void givenOutputStream_whenWriteSingleByteCalled_thenOutputCreated() throws IOException {
+
+ final File file = new File(filePath.toString());
+ OutputStreamExamples examples = new OutputStreamExamples();
+ examples.fileOutputStreamByteSingle(filePath.toString(), "Hello World!");
+ assertTrue(file.exists());
+ file.delete();
+ }
+
+ @Test
+ public void givenOutputStream_whenWriteByteSequenceCalled_thenOutputCreated() throws IOException {
+
+ final File file = new File(filePath.toString());
+ OutputStreamExamples examples = new OutputStreamExamples();
+ examples.fileOutputStreamByteSequence(filePath.toString(), "Hello World!");
+ assertTrue(file.exists());
+ file.delete();
+ }
+
+ @Test
+ public void givenOutputStream_whenWriteByteSubSequenceCalled_thenOutputCreated() throws IOException {
+
+ final File file = new File(filePath.toString());
+ OutputStreamExamples examples = new OutputStreamExamples();
+ examples.fileOutputStreamByteSubSequence(filePath.toString(), "Hello World!");
+ assertTrue(file.exists());
+ file.delete();
+ }
+
+ @Test
+ public void givenBufferedOutputStream_whenCalled_thenOutputCreated() throws IOException {
+
+ final File file = new File(filePath.toString());
+ OutputStreamExamples examples = new OutputStreamExamples();
+ examples.bufferedOutputStream(filePath.toString(), "Hello", "World!");
+ assertTrue(file.exists());
+ file.delete();
+ }
+
+ @Test
+ public void givenOutputStreamWriter_whenCalled_thenOutputCreated() throws IOException {
+
+ final File file = new File(filePath.toString());
+ OutputStreamExamples examples = new OutputStreamExamples();
+ examples.outputStreamWriter(filePath.toString(), "Hello World!");
+ assertTrue(file.exists());
+ file.delete();
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/classloader/CustomClassLoader.java b/core-java/src/main/java/com/baeldung/classloader/CustomClassLoader.java
index c44e863776..532adce1ab 100644
--- a/core-java/src/main/java/com/baeldung/classloader/CustomClassLoader.java
+++ b/core-java/src/main/java/com/baeldung/classloader/CustomClassLoader.java
@@ -1,11 +1,14 @@
package com.baeldung.classloader;
-import java.io.*;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
public class CustomClassLoader extends ClassLoader {
-
- public Class getClass(String name) throws ClassNotFoundException {
+ @Override
+ public Class findClass(String name) throws ClassNotFoundException {
byte[] b = loadClassFromFile(name);
return defineClass(name, b, 0, b.length);
}
diff --git a/core-java/src/test/java/com/baeldung/classloader/CustomClassLoaderUnitTest.java b/core-java/src/test/java/com/baeldung/classloader/CustomClassLoaderUnitTest.java
index ec35885b84..cabf9f7bdb 100644
--- a/core-java/src/test/java/com/baeldung/classloader/CustomClassLoaderUnitTest.java
+++ b/core-java/src/test/java/com/baeldung/classloader/CustomClassLoaderUnitTest.java
@@ -11,7 +11,7 @@ public class CustomClassLoaderUnitTest {
public void customLoader() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
CustomClassLoader customClassLoader = new CustomClassLoader();
- Class> c = customClassLoader.getClass(PrintClassLoader.class.getName());
+ Class> c = customClassLoader.findClass(PrintClassLoader.class.getName());
Object ob = c.newInstance();
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/datastructures/Main.kt b/core-kotlin/src/main/kotlin/com/baeldung/datastructures/Main.kt
new file mode 100644
index 0000000000..4fd8aa27c7
--- /dev/null
+++ b/core-kotlin/src/main/kotlin/com/baeldung/datastructures/Main.kt
@@ -0,0 +1,19 @@
+package com.baeldung.datastructures
+
+/**
+ * Example of how to use the {@link Node} class.
+ *
+ */
+fun main(args: Array) {
+ val tree = Node(4)
+ val keys = arrayOf(8, 15, 21, 3, 7, 2, 5, 10, 2, 3, 4, 6, 11)
+ for (key in keys) {
+ tree.insert(key)
+ }
+ val node = tree.find(4)!!
+ println("Node with value ${node.key} [left = ${node.left?.key}, right = ${node.right?.key}]")
+ println("Delete node with key = 3")
+ node.delete(3)
+ print("Tree content after the node elimination: ")
+ println(tree.visit().joinToString { it.toString() })
+}
diff --git a/core-kotlin/src/main/kotlin/com/baeldung/datastructures/Node.kt b/core-kotlin/src/main/kotlin/com/baeldung/datastructures/Node.kt
new file mode 100644
index 0000000000..b81afe1e4c
--- /dev/null
+++ b/core-kotlin/src/main/kotlin/com/baeldung/datastructures/Node.kt
@@ -0,0 +1,167 @@
+package com.baeldung.datastructures
+
+/**
+ * An ADT for a binary search tree.
+ * Note that this data type is neither immutable nor thread safe.
+ */
+class Node(
+ var key: Int,
+ var left: Node? = null,
+ var right: Node? = null) {
+
+ /**
+ * Return a node with given value. If no such node exists, return null.
+ * @param value
+ */
+ fun find(value: Int): Node? = when {
+ this.key > value -> left?.find(value)
+ this.key < value -> right?.find(value)
+ else -> this
+
+ }
+
+ /**
+ * Insert a given value into the tree.
+ * After insertion, the tree should contain a node with the given value.
+ * If the tree already contains the given value, nothing is performed.
+ * @param value
+ */
+ fun insert(value: Int) {
+ if (value > this.key) {
+ if (this.right == null) {
+ this.right = Node(value)
+ } else {
+ this.right?.insert(value)
+ }
+ } else if (value < this.key) {
+ if (this.left == null) {
+ this.left = Node(value)
+ } else {
+ this.left?.insert(value)
+ }
+ }
+ }
+
+ /**
+ * Delete the value from the given tree. If the tree does not contain the value, the tree remains unchanged.
+ * @param value
+ */
+ fun delete(value: Int) {
+ when {
+ value > key -> scan(value, this.right, this)
+ value < key -> scan(value, this.left, this)
+ else -> removeNode(this, null)
+ }
+ }
+
+ /**
+ * Scan the tree in the search of the given value.
+ * @param value
+ * @param node sub-tree that potentially might contain the sought value
+ * @param parent node's parent
+ */
+ private fun scan(value: Int, node: Node?, parent: Node?) {
+ if (node == null) {
+ System.out.println("value " + value
+ + " seems not present in the tree.")
+ return
+ }
+ when {
+ value > node.key -> scan(value, node.right, node)
+ value < node.key -> scan(value, node.left, node)
+ value == node.key -> removeNode(node, parent)
+ }
+
+ }
+
+ /**
+ * Remove the node.
+ *
+ * Removal process depends on how many children the node has.
+ *
+ * @param node node that is to be removed
+ * @param parent parent of the node to be removed
+ */
+ private fun removeNode(node: Node, parent: Node?) {
+ node.left?.let { leftChild ->
+ run {
+ node.right?.let {
+ removeTwoChildNode(node)
+ } ?: removeSingleChildNode(node, leftChild)
+ }
+ } ?: run {
+ node.right?.let { rightChild -> removeSingleChildNode(node, rightChild) } ?: removeNoChildNode(node, parent)
+ }
+
+
+ }
+
+ /**
+ * Remove the node without children.
+ * @param node
+ * @param parent
+ */
+ private fun removeNoChildNode(node: Node, parent: Node?) {
+ parent?.let { p ->
+ if (node == p.left) {
+ p.left = null
+ } else if (node == p.right) {
+ p.right = null
+ }
+ } ?: throw IllegalStateException(
+ "Can not remove the root node without child nodes")
+
+ }
+
+ /**
+ * Remove a node that has two children.
+ *
+ * The process of elimination is to find the biggest key in the left sub-tree and replace the key of the
+ * node that is to be deleted with that key.
+ */
+ private fun removeTwoChildNode(node: Node) {
+ val leftChild = node.left!!
+ leftChild.right?.let {
+ val maxParent = findParentOfMaxChild(leftChild)
+ maxParent.right?.let {
+ node.key = it.key
+ maxParent.right = null
+ } ?: throw IllegalStateException("Node with max child must have the right child!")
+
+ } ?: run {
+ node.key = leftChild.key
+ node.left = leftChild.left
+ }
+
+ }
+
+ /**
+ * Return a node whose right child contains the biggest value in the given sub-tree.
+ * Assume that the node n has a non-null right child.
+ *
+ * @param n
+ */
+ private fun findParentOfMaxChild(n: Node): Node {
+ return n.right?.let { r -> r.right?.let { findParentOfMaxChild(r) } ?: n }
+ ?: throw IllegalArgumentException("Right child must be non-null")
+
+ }
+
+ /**
+ * Remove a parent that has only one child.
+ * Removal is effectively is just coping the data from the child parent to the parent parent.
+ * @param parent Node to be deleted. Assume that it has just one child
+ * @param child Assume it is a child of the parent
+ */
+ private fun removeSingleChildNode(parent: Node, child: Node) {
+ parent.key = child.key
+ parent.left = child.left
+ parent.right = child.right
+ }
+
+ fun visit(): Array {
+ val a = left?.visit() ?: emptyArray()
+ val b = right?.visit() ?: emptyArray()
+ return a + arrayOf(key) + b
+ }
+}
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/datastructures/NodeTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/datastructures/NodeTest.kt
new file mode 100644
index 0000000000..8a46c5f6ec
--- /dev/null
+++ b/core-kotlin/src/test/kotlin/com/baeldung/datastructures/NodeTest.kt
@@ -0,0 +1,319 @@
+package com.baeldung.datastructures
+
+import org.junit.After
+import org.junit.Assert.*
+import org.junit.Before
+import org.junit.Test
+
+class NodeTest {
+
+ @Before
+ fun setUp() {
+ }
+
+ @After
+ fun tearDown() {
+ }
+
+ /**
+ * Test suit for finding the node by value
+ * Partition the tests as follows:
+ * 1. tree depth: 0, 1, > 1
+ * 2. pivot depth location: not present, 0, 1, 2, > 2
+ */
+
+ /**
+ * Find the node by value
+ * 1. tree depth: 0
+ * 2. pivot depth location: not present
+ */
+ @Test
+ fun givenDepthZero_whenPivotNotPresent_thenNull() {
+ val n = Node(1)
+ assertNull(n.find(2))
+ }
+
+ /**
+ * Find the node by value
+ * 1. tree depth: 0
+ * 2. pivot depth location: 0
+ */
+ @Test
+ fun givenDepthZero_whenPivotDepthZero_thenReturnNodeItself() {
+ val n = Node(1)
+ assertEquals(n, n.find(1))
+ }
+
+ /**
+ * Find the node by value
+ * 1. tree depth: 1
+ * 2. pivot depth location: not present
+ */
+ @Test
+ fun givenDepthOne_whenPivotNotPresent_thenNull() {
+ val n = Node(1, Node(0))
+ assertNull(n.find(2))
+ }
+
+ /**
+ * Find the node by value
+ * 1. tree depth: 1
+ * 2. pivot depth location: not present
+ */
+ @Test
+ fun givenDepthOne_whenPivotAtDepthOne_thenSuccess() {
+ val n = Node(1, Node(0))
+ assertEquals(n.left, n.find(0)
+ )
+ }
+
+ @Test
+ fun givenDepthTwo_whenPivotAtDepth2_then_Success() {
+ val left = Node(1, Node(0), Node(2))
+ val right = Node(5, Node(4), Node(6))
+ val n = Node(3, left, right)
+ assertEquals(left.left, n.find(0))
+ }
+
+
+ /**
+ * Test suit for inserting a value
+ * Partition the test as follows:
+ * 1. tree depth: 0, 1, 2, > 2
+ * 2. depth to insert: 0, 1, > 1
+ * 3. is duplicate: no, yes
+ * 4. sub-tree: left, right
+ */
+ /**
+ * Test for inserting a value
+ * 1. tree depth: 0
+ * 2. depth to insert: 1
+ * 3. is duplicate: no
+ * 4. sub-tree: right
+ */
+ @Test
+ fun givenTreeDepthZero_whenInsertNoDuplicateToRight_thenAddNode() {
+ val n = Node(1)
+ n.insert(2)
+ assertEquals(1, n.key)
+ with(n.right!!) {
+ assertEquals(2, key)
+ assertNull(left)
+ assertNull(right)
+ }
+ assertNull(n.left)
+ }
+
+ /**
+ * Test for inserting a value
+ * 1. tree depth: 0
+ * 2. depth to insert: 1
+ * 3. is duplicate: no
+ * 4. sub-tree: right
+ */
+ @Test
+ fun givenTreeDepthZero_whenInsertNoDuplicateToLeft_thenSuccess() {
+ val n = Node(1)
+ n.insert(0)
+ assertEquals(1, n.key)
+ with(n.left!!) {
+ assertEquals(0, key)
+ assertNull(left)
+ assertNull(right)
+ }
+ assertNull(n.right)
+ }
+
+ /**
+ * Test for inserting a value
+ * 1. tree depth: 0
+ * 2. depth to insert: 1
+ * 3. is duplicate: yes
+ */
+ @Test
+ fun givenTreeDepthZero_whenInsertDuplicate_thenSuccess() {
+ val n = Node(1)
+ n.insert(1)
+ assertEquals(1, n.key)
+ assertNull(n.right)
+ assertNull(n.left)
+ }
+
+
+ /**
+ * Test suit for inserting a value
+ * Partition the test as follows:
+ * 1. tree depth: 0, 1, 2, > 2
+ * 2. depth to insert: 0, 1, > 1
+ * 3. is duplicate: no, yes
+ * 4. sub-tree: left, right
+ */
+ /**
+ * Test for inserting a value
+ * 1. tree depth: 1
+ * 2. depth to insert: 1
+ * 3. is duplicate: no
+ * 4. sub-tree: right
+ */
+ @Test
+ fun givenTreeDepthOne_whenInsertNoDuplicateToRight_thenSuccess() {
+ val n = Node(10, Node(3))
+ n.insert(15)
+ assertEquals(10, n.key)
+ with(n.right!!) {
+ assertEquals(15, key)
+ assertNull(left)
+ assertNull(right)
+ }
+ with(n.left!!) {
+ assertEquals(3, key)
+ assertNull(left)
+ assertNull(right)
+ }
+ }
+
+ /**
+ * Test for inserting a value
+ * 1. tree depth: 1
+ * 2. depth to insert: 1
+ * 3. is duplicate: no
+ * 4. sub-tree: left
+ */
+ @Test
+ fun givenTreeDepthOne_whenInsertNoDuplicateToLeft_thenAddNode() {
+ val n = Node(10, null, Node(15))
+ n.insert(3)
+ assertEquals(10, n.key)
+ with(n.right!!) {
+ assertEquals(15, key)
+ assertNull(left)
+ assertNull(right)
+ }
+ with(n.left!!) {
+ assertEquals(3, key)
+ assertNull(left)
+ assertNull(right)
+ }
+ }
+
+ /**
+ * Test for inserting a value
+ * 1. tree depth: 1
+ * 2. depth to insert: 1
+ * 3. is duplicate: yes
+ */
+ @Test
+ fun givenTreeDepthOne_whenInsertDuplicate_thenNoChange() {
+ val n = Node(10, null, Node(15))
+ n.insert(15)
+ assertEquals(10, n.key)
+ with(n.right!!) {
+ assertEquals(15, key)
+ assertNull(left)
+ assertNull(right)
+ }
+ assertNull(n.left)
+ }
+
+ /**
+ * Test suit for removal
+ * Partition the input as follows:
+ * 1. tree depth: 0, 1, 2, > 2
+ * 2. value to delete: absent, present
+ * 3. # child nodes: 0, 1, 2
+ */
+ /**
+ * Test for removal value
+ * 1. tree depth: 0
+ * 2. value to delete: absent
+ */
+ @Test
+ fun givenTreeDepthZero_whenValueAbsent_thenNoChange() {
+ val n = Node(1)
+ n.delete(0)
+ assertEquals(1, n.key)
+ assertNull(n.left)
+ assertNull(n.right)
+ }
+
+ /**
+ * Test for removal
+ * 1. tree depth: 1
+ * 2. value to delete: absent
+ */
+ @Test
+ fun givenTreeDepthOne_whenValueAbsent_thenNoChange() {
+ val n = Node(1, Node(0), Node(2))
+ n.delete(3)
+ assertEquals(1, n.key)
+ assertEquals(2, n.right!!.key)
+ with(n.left!!) {
+ assertEquals(0, key)
+ assertNull(left)
+ assertNull(right)
+ }
+ with(n.right!!) {
+ assertNull(left)
+ assertNull(right)
+ }
+ }
+
+ /**
+ * Test suit for removal
+ * 1. tree depth: 1
+ * 2. value to delete: present
+ * 3. # child nodes: 0
+ */
+ @Test
+ fun givenTreeDepthOne_whenNodeToDeleteHasNoChildren_thenChangeTree() {
+ val n = Node(1, Node(0))
+ n.delete(0)
+ assertEquals(1, n.key)
+ assertNull(n.left)
+ assertNull(n.right)
+ }
+
+ /**
+ * Test suit for removal
+ * 1. tree depth: 2
+ * 2. value to delete: present
+ * 3. # child nodes: 1
+ */
+ @Test
+ fun givenTreeDepthTwo_whenNodeToDeleteHasOneChild_thenChangeTree() {
+ val n = Node(2, Node(0, null, Node(1)), Node(3))
+ n.delete(0)
+ assertEquals(2, n.key)
+ with(n.right!!) {
+ assertEquals(3, key)
+ assertNull(left)
+ assertNull(right)
+ }
+ with(n.left!!) {
+ assertEquals(1, key)
+ assertNull(left)
+ assertNull(right)
+ }
+ }
+
+ @Test
+ fun givenTreeDepthThree_whenNodeToDeleteHasTwoChildren_thenChangeTree() {
+ val l = Node(2, Node(1), Node(5, Node(4), Node(6)))
+ val r = Node(10, Node(9), Node(11))
+ val n = Node(8, l, r)
+ n.delete(8)
+ assertEquals(6, n.key)
+ with(n.left!!) {
+ assertEquals(2, key)
+ assertEquals(1, left!!.key)
+ assertEquals(5, right!!.key)
+ assertEquals(4, right!!.left!!.key)
+ }
+ with(n.right!!) {
+ assertEquals(10, key)
+ assertEquals(9, left!!.key)
+ assertEquals(11, right!!.key)
+ }
+ }
+
+}
diff --git a/flyway-cdi-extension/README.md b/flyway-cdi-extension/README.md
new file mode 100644
index 0000000000..3e03d5aee8
--- /dev/null
+++ b/flyway-cdi-extension/README.md
@@ -0,0 +1,3 @@
+### Relevant articles
+
+- [CDI Portable Extension and Flyway](https://www.baeldung.com/cdi-portable-extension)
diff --git a/hibernate5/README.md b/hibernate5/README.md
index b67ab7115f..b90f885c78 100644
--- a/hibernate5/README.md
+++ b/hibernate5/README.md
@@ -14,4 +14,5 @@
- [Bootstrapping JPA Programmatically in Java](http://www.baeldung.com/java-bootstrap-jpa)
- [Optimistic Locking in JPA](http://www.baeldung.com/jpa-optimistic-locking)
- [Hibernate Entity Lifecycle](https://www.baeldung.com/hibernate-entity-lifecycle)
+- [Mapping A Hibernate Query to a Custom Class](https://www.baeldung.com/hibernate-query-to-custom-class)
- [@JoinColumn Annotation Explained](https://www.baeldung.com/jpa-join-column)
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/pojo/User.java b/hibernate5/src/main/java/com/baeldung/hibernate/pojo/User.java
index 90203d29ec..ccbdf80bf1 100644
--- a/hibernate5/src/main/java/com/baeldung/hibernate/pojo/User.java
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/pojo/User.java
@@ -4,13 +4,23 @@ import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
-import javax.persistence.SequenceGenerator;
+
+import org.hibernate.annotations.GenericGenerator;
+import org.hibernate.annotations.Parameter;
@Entity
public class User {
@Id
- @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence-generator")
- @SequenceGenerator(name = "sequence-generator", sequenceName = "user_sequence", initialValue = 4)
+ @GeneratedValue(generator = "sequence-generator")
+ @GenericGenerator(
+ name = "sequence-generator",
+ strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
+ parameters = {
+ @Parameter(name = "sequence_name", value = "user_sequence"),
+ @Parameter(name = "initial_value", value = "4"),
+ @Parameter(name = "increment_size", value = "1")
+ }
+ )
private long userId;
public long getUserId() {
diff --git a/java-dates/pom.xml b/java-dates/pom.xml
index 13e2a077e1..2618fad1d4 100644
--- a/java-dates/pom.xml
+++ b/java-dates/pom.xml
@@ -80,7 +80,7 @@
2.10
3.6.1
- 9
- 9
+ 1.9
+ 1.9
diff --git a/java-dates/src/test/java/com/baeldung/date/DateDiffUnitTest.java b/java-dates/src/test/java/com/baeldung/date/DateDiffUnitTest.java
index 545009a2a9..58d192bfdb 100644
--- a/java-dates/src/test/java/com/baeldung/date/DateDiffUnitTest.java
+++ b/java-dates/src/test/java/com/baeldung/date/DateDiffUnitTest.java
@@ -5,7 +5,9 @@ import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
+import java.time.LocalDate;
import java.time.LocalDateTime;
+import java.time.Period;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
@@ -26,6 +28,17 @@ public class DateDiffUnitTest {
assertEquals(diff, 6);
}
+
+ @Test
+ public void givenTwoDatesInJava8_whenDifferentiating_thenWeGetSix() {
+ LocalDate now = LocalDate.now();
+ LocalDate sixDaysBehind = now.minusDays(6);
+
+ Period period = Period.between(now, sixDaysBehind);
+ int diff = period.getDays();
+
+ assertEquals(diff, 6);
+ }
@Test
public void givenTwoDateTimesInJava8_whenDifferentiating_thenWeGetSix() {
diff --git a/java-dates/src/test/java/com/baeldung/datetime/DateTimeFormatterUnitTest.java b/java-dates/src/test/java/com/baeldung/datetime/DateTimeFormatterUnitTest.java
new file mode 100644
index 0000000000..f3b2b11893
--- /dev/null
+++ b/java-dates/src/test/java/com/baeldung/datetime/DateTimeFormatterUnitTest.java
@@ -0,0 +1,158 @@
+package com.baeldung.datetime;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.time.format.FormatStyle;
+import java.time.temporal.ChronoUnit;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class DateTimeFormatterUnitTest {
+
+ @Test
+ public void givenDefaultUsLocaleAndDateTimeAndPattern_whenFormatWithDifferentLocales_thenGettingLocalizedDateTimes() {
+ Locale.setDefault(Locale.US);
+ LocalDateTime localDateTime = LocalDateTime.of(2018, 1, 1, 10, 15, 50, 500);
+ String pattern = "dd-MMMM-yyyy HH:mm:ss.SSS";
+
+ DateTimeFormatter defaultTimeFormatter = DateTimeFormatter.ofPattern(pattern);
+ DateTimeFormatter plTimeFormatter = DateTimeFormatter.ofPattern(pattern, new Locale("pl", "PL"));
+ DateTimeFormatter deTimeFormatter = DateTimeFormatter.ofPattern(pattern).withLocale(Locale.GERMANY);
+
+ Assert.assertEquals("01-January-2018 10:15:50.000", defaultTimeFormatter.format(localDateTime));
+ Assert.assertEquals("01-stycznia-2018 10:15:50.000", plTimeFormatter.format(localDateTime));
+ Assert.assertEquals("01-Januar-2018 10:15:50.000", deTimeFormatter.format(localDateTime));
+ }
+
+ @Test
+ public void givenDateTimeAndTimeZone_whenFormatWithDifferentLocales_thenGettingLocalizedZonedDateTimes() {
+ Locale.setDefault(Locale.US);
+ LocalDateTime localDateTime = LocalDateTime.of(2018, 1, 1, 10, 15, 50, 500);
+ ZoneId losAngelesTimeZone = TimeZone.getTimeZone("America/Los_Angeles").toZoneId();
+
+ DateTimeFormatter localizedFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL);
+ DateTimeFormatter frLocalizedFormatter =
+ DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(Locale.FRANCE);
+ String formattedDateTime = localizedFormatter.format(ZonedDateTime.of(localDateTime, losAngelesTimeZone));
+ String frFormattedDateTime = frLocalizedFormatter.format(ZonedDateTime.of(localDateTime, losAngelesTimeZone));
+
+ Assert.assertEquals("Monday, January 1, 2018 10:15:50 AM PST", formattedDateTime);
+ Assert.assertEquals("lundi 1 janvier 2018 10 h 15 PST", frFormattedDateTime);
+ }
+
+ @Test
+ public void shouldPrintFormattedDate() {
+ String europeanDatePattern = "dd.MM.yyyy";
+ DateTimeFormatter europeanDateFormatter = DateTimeFormatter.ofPattern(europeanDatePattern);
+ LocalDate summerDay = LocalDate.of(2016, 7, 31);
+ Assert.assertEquals("31.07.2016", europeanDateFormatter.format(summerDay));
+ }
+
+ @Test
+ public void shouldPrintFormattedTime24() {
+ String timeColonPattern = "HH:mm:ss";
+ DateTimeFormatter timeColonFormatter = DateTimeFormatter.ofPattern(timeColonPattern);
+ LocalTime colonTime = LocalTime.of(17, 35, 50);
+ Assert.assertEquals("17:35:50", timeColonFormatter.format(colonTime));
+ }
+
+ @Test
+ public void shouldPrintFormattedTimeWithMillis() {
+ String timeColonPattern = "HH:mm:ss SSS";
+ DateTimeFormatter timeColonFormatter = DateTimeFormatter.ofPattern(timeColonPattern);
+ LocalTime colonTime = LocalTime.of(17, 35, 50).plus(329, ChronoUnit.MILLIS);
+ Assert.assertEquals("17:35:50 329", timeColonFormatter.format(colonTime));
+ }
+
+ @Test
+ public void shouldPrintFormattedTimePM() {
+ String timeColonPattern = "hh:mm:ss a";
+ DateTimeFormatter timeColonFormatter = DateTimeFormatter.ofPattern(timeColonPattern);
+ LocalTime colonTime = LocalTime.of(17, 35, 50);
+ Assert.assertEquals("05:35:50 PM", timeColonFormatter.format(colonTime));
+ }
+
+ @Test
+ public void shouldPrintFormattedUTCRelatedZonedDateTime() {
+ String newYorkDateTimePattern = "dd.MM.yyyy HH:mm z";
+ DateTimeFormatter newYorkDateFormatter = DateTimeFormatter.ofPattern(newYorkDateTimePattern);
+ LocalDateTime summerDay = LocalDateTime.of(2016, 7, 31, 14, 15);
+ Assert.assertEquals("31.07.2016 14:15 UTC-04:00", newYorkDateFormatter.format(ZonedDateTime.of(summerDay, ZoneId.of("UTC-4"))));
+ }
+
+ @Test
+ public void shouldPrintFormattedNewYorkZonedDateTime() {
+ String newYorkDateTimePattern = "dd.MM.yyyy HH:mm z";
+ DateTimeFormatter newYorkDateFormatter = DateTimeFormatter.ofPattern(newYorkDateTimePattern);
+ LocalDateTime summerDay = LocalDateTime.of(2016, 7, 31, 14, 15);
+ Assert.assertEquals("31.07.2016 14:15 EDT", newYorkDateFormatter.format(ZonedDateTime.of(summerDay, ZoneId.of("America/New_York"))));
+ }
+
+ @Test
+ public void shouldPrintStyledDate() {
+ LocalDate anotherSummerDay = LocalDate.of(2016, 8, 23);
+ Assert.assertEquals("Tuesday, August 23, 2016", DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(anotherSummerDay));
+ Assert.assertEquals("August 23, 2016", DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG).format(anotherSummerDay));
+ Assert.assertEquals("Aug 23, 2016", DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).format(anotherSummerDay));
+ Assert.assertEquals("8/23/16", DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).format(anotherSummerDay));
+ }
+
+ @Test
+ public void shouldPrintStyledDateTime() {
+ LocalDateTime anotherSummerDay = LocalDateTime.of(2016, 8, 23, 13, 12, 45);
+ Assert.assertEquals("Tuesday, August 23, 2016 1:12:45 PM EET", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withZone(ZoneId.of("Europe/Helsinki")).format(anotherSummerDay));
+ Assert.assertEquals("August 23, 2016 1:12:45 PM EET", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG).withZone(ZoneId.of("Europe/Helsinki")).format(anotherSummerDay));
+ Assert.assertEquals("Aug 23, 2016 1:12:45 PM", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withZone(ZoneId.of("Europe/Helsinki")).format(anotherSummerDay));
+ Assert.assertEquals("8/23/16 1:12 PM", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withZone(ZoneId.of("Europe/Helsinki")).format(anotherSummerDay));
+ }
+
+ @Test
+ public void shouldPrintFormattedDateTimeWithPredefined() {
+ Assert.assertEquals("2018-03-09", DateTimeFormatter.ISO_LOCAL_DATE.format(LocalDate.of(2018, 3, 9)));
+ Assert.assertEquals("2018-03-09-03:00", DateTimeFormatter.ISO_OFFSET_DATE.format(LocalDate.of(2018, 3, 9).atStartOfDay(ZoneId.of("UTC-3"))));
+ Assert.assertEquals("Fri, 9 Mar 2018 00:00:00 -0300", DateTimeFormatter.RFC_1123_DATE_TIME.format(LocalDate.of(2018, 3, 9).atStartOfDay(ZoneId.of("UTC-3"))));
+ }
+
+ @Test
+ public void shouldParseDateTime() {
+ Assert.assertEquals(LocalDate.of(2018, 3, 12), LocalDate.from(DateTimeFormatter.ISO_LOCAL_DATE.parse("2018-03-09")).plusDays(3));
+ }
+
+ @Test
+ public void shouldParseFormatStyleFull() {
+ ZonedDateTime dateTime = ZonedDateTime.from(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).parse("Tuesday, August 23, 2016 1:12:45 PM EET"));
+ Assert.assertEquals(ZonedDateTime.of(LocalDateTime.of(2016, 8, 23, 22, 12, 45), ZoneId.of("Europe/Bucharest")), dateTime.plusHours(9));
+ }
+
+ @Test
+ public void shouldParseDateWithCustomFormatter() {
+ DateTimeFormatter europeanDateFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
+ Assert.assertFalse(LocalDate.from(europeanDateFormatter.parse("15.08.2014")).isLeapYear());
+ }
+
+ @Test
+ public void shouldParseTimeWithCustomFormatter() {
+ DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mm:ss a");
+ Assert.assertTrue(LocalTime.from(timeFormatter.parse("12:25:30 AM")).isBefore(LocalTime.NOON));
+ }
+
+ @Test
+ public void shouldParseZonedDateTimeWithCustomFormatter() {
+ DateTimeFormatter zonedFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm z");
+ Assert.assertEquals(7200, ZonedDateTime.from(zonedFormatter.parse("31.07.2016 14:15 GMT+02:00")).getOffset().getTotalSeconds());
+ }
+
+ @Test(expected = DateTimeParseException.class)
+ public void shouldExpectAnExceptionIfDateTimeStringNotMatchPattern() {
+ DateTimeFormatter zonedFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm z");
+ ZonedDateTime.from(zonedFormatter.parse("31.07.2016 14:15"));
+ }
+}
diff --git a/java-dates/src/test/java/com/baeldung/zoneddatetime/ZonedDateTimeUnitTest.java b/java-dates/src/test/java/com/baeldung/zoneddatetime/ZonedDateTimeUnitTest.java
new file mode 100644
index 0000000000..355fef35c6
--- /dev/null
+++ b/java-dates/src/test/java/com/baeldung/zoneddatetime/ZonedDateTimeUnitTest.java
@@ -0,0 +1,43 @@
+package com.baeldung.zoneddatetime;
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.logging.Logger;
+
+import org.junit.Test;
+
+public class ZonedDateTimeUnitTest {
+
+ private static final Logger log = Logger.getLogger(ZonedDateTimeUnitTest.class.getName());
+
+ @Test
+ public void testZonedDateTimeToString() {
+
+ ZonedDateTime zonedDateTimeNow = ZonedDateTime.now(ZoneId.of("UTC"));
+ ZonedDateTime zonedDateTimeOf = ZonedDateTime.of(2018, 01, 01, 0, 0, 0, 0, ZoneId.of("UTC"));
+
+ LocalDateTime localDateTime = LocalDateTime.now();
+ ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.of("UTC"));
+
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy - hh:mm:ss Z");
+ String formattedString = zonedDateTime.format(formatter);
+
+ DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("MM/dd/yyyy - hh:mm:ss z");
+ String formattedString2 = zonedDateTime.format(formatter2);
+
+ log.info(formattedString);
+ log.info(formattedString2);
+
+ }
+
+ @Test
+ public void testZonedDateTimeFromString() {
+
+ ZonedDateTime zonedDateTime = ZonedDateTime.parse("2011-12-03T10:15:30+01:00", DateTimeFormatter.ISO_ZONED_DATE_TIME);
+
+ log.info(zonedDateTime.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
+ }
+
+}
diff --git a/java-difference-date/README.md b/java-difference-date/README.md
deleted file mode 100644
index 2a024c27a2..0000000000
--- a/java-difference-date/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-## Relevant articles:
-
-- [Period and Duration in Java](http://www.baeldung.com/java-period-duration)
-- [Introduction to the Java 8 Date/Time API](http://www.baeldung.com/java-8-date-time-intro)
-- [Migrating to the New Java 8 Date Time API](http://www.baeldung.com/migrating-to-java-8-date-time-api)
\ No newline at end of file
diff --git a/java-difference-date/pom.xml b/java-difference-date/pom.xml
deleted file mode 100644
index 8c87afc0a2..0000000000
--- a/java-difference-date/pom.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
- 4.0.0
- com.baeldung
- java-difference-date
- 0.0.1-SNAPSHOT
- jar
- java-difference-date
- Difference between two dates in java
-
-
- com.baeldung
- parent-modules
- 1.0.0-SNAPSHOT
-
-
-
-
- joda-time
- joda-time
- ${joda-time.version}
-
-
- com.darwinsys
- hirondelle-date4j
- ${hirondelle-date4j.version}
-
-
-
-
- 2.9.9
- 1.5.1
-
-
-
diff --git a/java-difference-date/src/test/java/com/baeldung/DateDiffUnitTest.java b/java-difference-date/src/test/java/com/baeldung/DateDiffUnitTest.java
deleted file mode 100644
index 2c5323be6f..0000000000
--- a/java-difference-date/src/test/java/com/baeldung/DateDiffUnitTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.baeldung;
-
-import org.joda.time.DateTime;
-import org.junit.Test;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.time.Duration;
-import java.time.ZonedDateTime;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
-import java.util.concurrent.TimeUnit;
-
-import static org.junit.Assert.assertEquals;
-
-public class DateDiffUnitTest {
- @Test
- public void givenTwoDatesBeforeJava8_whenDifferentiating_thenWeGetSix() throws ParseException {
- SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH);
- Date firstDate = sdf.parse("06/24/2017");
- Date secondDate = sdf.parse("06/30/2017");
-
- long diffInMillies = Math.abs(secondDate.getTime() - firstDate.getTime());
- long diff = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);
-
- assertEquals(diff, 6);
- }
-
- @Test
- public void givenTwoDatesInJava8_whenDifferentiating_thenWeGetSix() {
- ZonedDateTime now = ZonedDateTime.now();
- ZonedDateTime sixDaysBehind = now.minusDays(6);
-
- Duration duration = Duration.between(now, sixDaysBehind);
- long diff = Math.abs(duration.toDays());
-
- assertEquals(diff, 6);
- }
-
- @Test
- public void givenTwoDatesInJodaTime_whenDifferentiating_thenWeGetSix() {
- DateTime now = DateTime.now();
- DateTime sixDaysBehind = now.minusDays(6);
-
- org.joda.time.Duration duration = new org.joda.time.Duration(now, sixDaysBehind);
- long diff = Math.abs(duration.getStandardDays());
-
- assertEquals(diff, 6);
- }
-
- @Test
- public void givenTwoDatesInDate4j_whenDifferentiating_thenWeGetSix() {
- hirondelle.date4j.DateTime now = hirondelle.date4j.DateTime.now(TimeZone.getDefault());
- hirondelle.date4j.DateTime sixDaysBehind = now.minusDays(6);
-
- long diff = Math.abs(now.numDaysFrom(sixDaysBehind));
-
- assertEquals(diff, 6);
- }
-}
\ No newline at end of file
diff --git a/java-strings/README.md b/java-strings/README.md
index 249f1a351a..b12fc75f30 100644
--- a/java-strings/README.md
+++ b/java-strings/README.md
@@ -27,6 +27,7 @@
- [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)
+- [Get Substring from String in Java](https://www.baeldung.com/java-substring)
- [Converting a Stack Trace to a String in Java](https://www.baeldung.com/java-stacktrace-to-string)
- [Sorting a String Alphabetically in Java](https://www.baeldung.com/java-sort-string-alphabetically)
- [Remove Emojis from a Java String](https://www.baeldung.com/java-string-remove-emojis)
diff --git a/javaxval/pom.xml b/javaxval/pom.xml
index 63cb4c1d1d..0263fb68af 100644
--- a/javaxval/pom.xml
+++ b/javaxval/pom.xml
@@ -33,7 +33,7 @@
${javax.el-api.version}
- org.glassfish.web
+ org.glassfish
javax.el
${javax.el.version}
@@ -63,11 +63,11 @@
2.0.1.Final
- 6.0.7.Final
+ 6.0.13.Final
3.0.0
- 2.2.6
+ 3.0.0
5.0.2.RELEASE
4.12
3.11.1
-
\ No newline at end of file
+
diff --git a/jee-7-security/README.md b/jee-7-security/README.md
new file mode 100644
index 0000000000..314de6d957
--- /dev/null
+++ b/jee-7-security/README.md
@@ -0,0 +1,2 @@
+### Relevant Articles:
+- [Securing Java EE with Spring Security](http://www.baeldung.com/java-ee-spring-security)
diff --git a/jee-7-security/pom.xml b/jee-7-security/pom.xml
new file mode 100644
index 0000000000..622ca19903
--- /dev/null
+++ b/jee-7-security/pom.xml
@@ -0,0 +1,102 @@
+
+
+ 4.0.0
+ jee-7-security
+ 1.0-SNAPSHOT
+ war
+ jee-7-security
+ JavaEE 7 Spring Security Application
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ javax
+ javaee-api
+ ${javaee_api.version}
+ provided
+
+
+ com.sun.faces
+ jsf-api
+ ${com.sun.faces.jsf.version}
+
+
+ com.sun.faces
+ jsf-impl
+ ${com.sun.faces.jsf.version}
+
+
+ javax.servlet
+ jstl
+ ${jstl.version}
+
+
+ javax.servlet
+ javax.servlet-api
+ ${javax.servlet-api.version}
+
+
+ javax.servlet.jsp
+ jsp-api
+ ${jsp-api.version}
+ provided
+
+
+ taglibs
+ standard
+ ${taglibs.standard.version}
+
+
+
+ javax.mvc
+ javax.mvc-api
+ 1.0-pr
+
+
+
+ org.springframework.security
+ spring-security-web
+ ${org.springframework.security.version}
+
+
+
+ org.springframework.security
+ spring-security-config
+ ${org.springframework.security.version}
+
+
+ org.springframework.security
+ spring-security-taglibs
+ ${org.springframework.security.version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ ${maven-war-plugin.version}
+
+ src/main/webapp
+ false
+
+
+
+
+
+
+ 7.0
+ 2.2.14
+ 2.2
+ 1.1.2
+ 4.2.3.RELEASE
+
+
+
diff --git a/jee-7/src/main/java/com/baeldung/springSecurity/SecurityWebApplicationInitializer.java b/jee-7-security/src/main/java/com/baeldung/springsecurity/SecurityWebApplicationInitializer.java
similarity index 88%
rename from jee-7/src/main/java/com/baeldung/springSecurity/SecurityWebApplicationInitializer.java
rename to jee-7-security/src/main/java/com/baeldung/springsecurity/SecurityWebApplicationInitializer.java
index e6a05f7b71..e3e2ed80e6 100644
--- a/jee-7/src/main/java/com/baeldung/springSecurity/SecurityWebApplicationInitializer.java
+++ b/jee-7-security/src/main/java/com/baeldung/springsecurity/SecurityWebApplicationInitializer.java
@@ -1,4 +1,4 @@
-package com.baeldung.springSecurity;
+package com.baeldung.springsecurity;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
diff --git a/jee-7/src/main/java/com/baeldung/springSecurity/SpringSecurityConfig.java b/jee-7-security/src/main/java/com/baeldung/springsecurity/SpringSecurityConfig.java
similarity index 97%
rename from jee-7/src/main/java/com/baeldung/springSecurity/SpringSecurityConfig.java
rename to jee-7-security/src/main/java/com/baeldung/springsecurity/SpringSecurityConfig.java
index bda8930f36..70be1f91ce 100644
--- a/jee-7/src/main/java/com/baeldung/springSecurity/SpringSecurityConfig.java
+++ b/jee-7-security/src/main/java/com/baeldung/springsecurity/SpringSecurityConfig.java
@@ -1,4 +1,4 @@
-package com.baeldung.springSecurity;
+package com.baeldung.springsecurity;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
diff --git a/jee-7/src/main/java/com/baeldung/springSecurity/controller/HomeController.java b/jee-7-security/src/main/java/com/baeldung/springsecurity/controller/HomeController.java
similarity index 89%
rename from jee-7/src/main/java/com/baeldung/springSecurity/controller/HomeController.java
rename to jee-7-security/src/main/java/com/baeldung/springsecurity/controller/HomeController.java
index 53fd9f4b81..1662f38609 100644
--- a/jee-7/src/main/java/com/baeldung/springSecurity/controller/HomeController.java
+++ b/jee-7-security/src/main/java/com/baeldung/springsecurity/controller/HomeController.java
@@ -1,4 +1,4 @@
-package com.baeldung.springSecurity.controller;
+package com.baeldung.springsecurity.controller;
import javax.mvc.annotation.Controller;
import javax.ws.rs.GET;
diff --git a/jee-7/src/main/java/com/baeldung/springSecurity/controller/LoginController.java b/jee-7-security/src/main/java/com/baeldung/springsecurity/controller/LoginController.java
similarity index 82%
rename from jee-7/src/main/java/com/baeldung/springSecurity/controller/LoginController.java
rename to jee-7-security/src/main/java/com/baeldung/springsecurity/controller/LoginController.java
index a7e7bb471d..45d7ff3d2c 100644
--- a/jee-7/src/main/java/com/baeldung/springSecurity/controller/LoginController.java
+++ b/jee-7-security/src/main/java/com/baeldung/springsecurity/controller/LoginController.java
@@ -1,4 +1,4 @@
-package com.baeldung.springSecurity.controller;
+package com.baeldung.springsecurity.controller;
import javax.mvc.annotation.Controller;
import javax.ws.rs.GET;
diff --git a/jee-7-security/src/main/resources/logback.xml b/jee-7-security/src/main/resources/logback.xml
new file mode 100644
index 0000000000..c8c077ba1d
--- /dev/null
+++ b/jee-7-security/src/main/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jee-7-security/src/main/webapp/WEB-INF/beans.xml b/jee-7-security/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/jee-7-security/src/main/webapp/WEB-INF/faces-config.xml b/jee-7-security/src/main/webapp/WEB-INF/faces-config.xml
new file mode 100644
index 0000000000..1f4085458f
--- /dev/null
+++ b/jee-7-security/src/main/webapp/WEB-INF/faces-config.xml
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/jee-7/src/main/webapp/WEB-INF/spring/security.xml b/jee-7-security/src/main/webapp/WEB-INF/spring/security.xml
similarity index 100%
rename from jee-7/src/main/webapp/WEB-INF/spring/security.xml
rename to jee-7-security/src/main/webapp/WEB-INF/spring/security.xml
diff --git a/jee-7/src/main/webapp/WEB-INF/views/admin.jsp b/jee-7-security/src/main/webapp/WEB-INF/views/admin.jsp
similarity index 100%
rename from jee-7/src/main/webapp/WEB-INF/views/admin.jsp
rename to jee-7-security/src/main/webapp/WEB-INF/views/admin.jsp
diff --git a/jee-7/src/main/webapp/WEB-INF/views/home.jsp b/jee-7-security/src/main/webapp/WEB-INF/views/home.jsp
similarity index 100%
rename from jee-7/src/main/webapp/WEB-INF/views/home.jsp
rename to jee-7-security/src/main/webapp/WEB-INF/views/home.jsp
diff --git a/jee-7/src/main/webapp/WEB-INF/views/login.jsp b/jee-7-security/src/main/webapp/WEB-INF/views/login.jsp
similarity index 100%
rename from jee-7/src/main/webapp/WEB-INF/views/login.jsp
rename to jee-7-security/src/main/webapp/WEB-INF/views/login.jsp
diff --git a/jee-7/src/main/webapp/WEB-INF/views/user.jsp b/jee-7-security/src/main/webapp/WEB-INF/views/user.jsp
similarity index 100%
rename from jee-7/src/main/webapp/WEB-INF/views/user.jsp
rename to jee-7-security/src/main/webapp/WEB-INF/views/user.jsp
diff --git a/jee-7-security/src/main/webapp/WEB-INF/web.xml b/jee-7-security/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000000..e656ffc5be
--- /dev/null
+++ b/jee-7-security/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,71 @@
+
+
+
+
+ Faces Servlet
+ javax.faces.webapp.FacesServlet
+
+
+ Faces Servlet
+ *.jsf
+
+
+ javax.faces.PROJECT_STAGE
+ Development
+
+
+ State saving method: 'client' or 'server' (default). See JSF Specification section 2.5.2
+ javax.faces.STATE_SAVING_METHOD
+ client
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ index.jsf
+ welcome.jsf
+ index.html
+ index.jsp
+
+
\ No newline at end of file
diff --git a/jee-7/src/main/webapp/index.jsp b/jee-7-security/src/main/webapp/index.jsp
similarity index 100%
rename from jee-7/src/main/webapp/index.jsp
rename to jee-7-security/src/main/webapp/index.jsp
diff --git a/jee-7/src/main/webapp/secure.jsp b/jee-7-security/src/main/webapp/secure.jsp
similarity index 100%
rename from jee-7/src/main/webapp/secure.jsp
rename to jee-7-security/src/main/webapp/secure.jsp
diff --git a/jee-7/README.md b/jee-7/README.md
index f0bd65fdf2..a2493e561b 100644
--- a/jee-7/README.md
+++ b/jee-7/README.md
@@ -5,5 +5,3 @@
- [Introduction to JAX-WS](http://www.baeldung.com/jax-ws)
- [A Guide to Java EE Web-Related Annotations](http://www.baeldung.com/javaee-web-annotations)
- [Introduction to Testing with Arquillian](http://www.baeldung.com/arquillian)
-- [Securing Java EE with Spring Security](http://www.baeldung.com/java-ee-spring-security)
-- [A Guide to Java EE Web-Related Annotations](https://www.baeldung.com/javaee-web-annotations)
\ No newline at end of file
diff --git a/jee-7/src/main/java/com/baeldung/springSecurity/ApplicationConfig.java b/jee-7/src/main/java/com/baeldung/springSecurity/ApplicationConfig.java
deleted file mode 100755
index f8e7982253..0000000000
--- a/jee-7/src/main/java/com/baeldung/springSecurity/ApplicationConfig.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.baeldung.springSecurity;
-
-import javax.ws.rs.ApplicationPath;
-import javax.ws.rs.core.Application;
-
-/**
- * Application class required by JAX-RS. If you don't want to have any
- * prefix in the URL, you can set the application path to "/".
- */
-@ApplicationPath("/")
-public class ApplicationConfig extends Application {
-
-}
diff --git a/jee-7/src/main/webapp/WEB-INF/web.xml b/jee-7/src/main/webapp/WEB-INF/web.xml
index 1bcbb96e24..e656ffc5be 100644
--- a/jee-7/src/main/webapp/WEB-INF/web.xml
+++ b/jee-7/src/main/webapp/WEB-INF/web.xml
@@ -1,5 +1,8 @@
-
+
-
- org.apache.crunch
- crunch-core
- ${org.apache.crunch.crunch-core.version}
-
-
- org.apache.hadoop
- hadoop-client
- ${org.apache.hadoop.hadoop-client}
- provided
-
+
+ org.apache.crunch
+ crunch-core
+ ${org.apache.crunch.crunch-core.version}
+
+
+ org.apache.hadoop
+ hadoop-client
+ ${org.apache.hadoop.hadoop-client}
+ provided
+
-
- commons-cli
- commons-cli
- 1.2
- provided
-
-
- commons-io
- commons-io
- 2.1
- provided
-
-
- commons-httpclient
- commons-httpclient
- 3.0.1
- provided
-
-
- commons-codec
- commons-codec
-
-
-
+
+ commons-cli
+ commons-cli
+ 1.2
+ provided
+
+
+ commons-io
+ commons-io
+ 2.1
+ provided
+
+
+ commons-httpclient
+ commons-httpclient
+ 3.0.1
+ provided
+
+
+ commons-codec
+ commons-codec
+
+
+
org.apache.flink
flink-connector-kafka-0.11_2.11
@@ -249,7 +249,32 @@
${awaitility.version}
test
+
+ io.ebean
+ ebean
+ ${ebean.version}
+
+
+ org.slf4j
+ slf4j-api
+ ${slf4j.version}
+
+
+ ch.qos.logback
+ logback-classic
+ ${logback.version}
+
+
+ ch.qos.logback
+ logback-core
+ ${logback.version}
+
+
+ org.slf4j
+ slf4j-log4j12
+ ${slf4j.version}
+
@@ -354,31 +379,48 @@
-
- org.apache.maven.plugins
- maven-assembly-plugin
- 2.3
-
-
- src/main/assembly/hadoop-job.xml
-
-
-
- com.baeldung.crunch.WordCount
-
-
-
-
-
- make-assembly
- package
-
- single
-
-
-
-
-
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 2.3
+
+
+ src/main/assembly/hadoop-job.xml
+
+
+
+ com.baeldung.crunch.WordCount
+
+
+
+
+
+ make-assembly
+ package
+
+ single
+
+
+
+
+
+ io.ebean
+ ebean-maven-plugin
+ 11.11.2
+
+
+
+ main
+ process-classes
+
+ debug=1
+
+
+ enhance
+
+
+
+
@@ -415,7 +457,10 @@
5.0.4
1.6.0.1
0.15.0
- 2.2.0
+ 2.2.0
+ 11.22.4
+ 1.7.25
+ 1.0.1
diff --git a/libraries-data/src/main/java/com/baeldung/ebean/app/App.java b/libraries-data/src/main/java/com/baeldung/ebean/app/App.java
new file mode 100644
index 0000000000..44a4fa8562
--- /dev/null
+++ b/libraries-data/src/main/java/com/baeldung/ebean/app/App.java
@@ -0,0 +1,75 @@
+package com.baeldung.ebean.app;
+
+import java.util.Arrays;
+
+import com.baeldung.ebean.model.Address;
+import com.baeldung.ebean.model.Customer;
+
+import io.ebean.Ebean;
+import io.ebean.EbeanServer;
+import io.ebean.annotation.Transactional;
+
+public class App {
+
+ public static void main(String[] args) {
+ insertAndDeleteInsideTransaction();
+ crudOperations();
+ queryCustomers();
+ }
+
+ @Transactional
+ public static void insertAndDeleteInsideTransaction() {
+
+ Customer c1 = getCustomer();
+ EbeanServer server = Ebean.getDefaultServer();
+ server.save(c1);
+ Customer foundC1 = server.find(Customer.class, c1.getId());
+ server.delete(foundC1);
+ }
+
+ public static void crudOperations() {
+
+ Address a1 = new Address("5, Wide Street", null, "New York");
+ Customer c1 = new Customer("John Wide", a1);
+
+ EbeanServer server = Ebean.getDefaultServer();
+ server.save(c1);
+
+ c1.setName("Jane Wide");
+ c1.setAddress(null);
+ server.save(c1);
+
+ Customer foundC1 = Ebean.find(Customer.class, c1.getId());
+
+ Ebean.delete(foundC1);
+ }
+
+ public static void queryCustomers() {
+ Address a1 = new Address("1, Big Street", null, "New York");
+ Customer c1 = new Customer("Big John", a1);
+
+ Address a2 = new Address("2, Big Street", null, "New York");
+ Customer c2 = new Customer("Big John", a2);
+
+ Address a3 = new Address("3, Big Street", null, "San Jose");
+ Customer c3 = new Customer("Big Bob", a3);
+
+ Ebean.saveAll(Arrays.asList(c1, c2, c3));
+
+ Customer customer = Ebean.find(Customer.class)
+ .select("name")
+ .fetch("address", "city")
+ .where()
+ .eq("city", "San Jose")
+ .findOne();
+
+ Ebean.deleteAll(Arrays.asList(c1, c2, c3));
+ }
+
+ private static Customer getCustomer() {
+ Address a1 = new Address("1, Big Street", null, "New York");
+ Customer c1 = new Customer("Big John", a1);
+ return c1;
+ }
+
+}
diff --git a/libraries-data/src/main/java/com/baeldung/ebean/app/App2.java b/libraries-data/src/main/java/com/baeldung/ebean/app/App2.java
new file mode 100644
index 0000000000..fba77007c6
--- /dev/null
+++ b/libraries-data/src/main/java/com/baeldung/ebean/app/App2.java
@@ -0,0 +1,26 @@
+package com.baeldung.ebean.app;
+
+import java.util.Properties;
+
+import io.ebean.EbeanServer;
+import io.ebean.EbeanServerFactory;
+import io.ebean.config.ServerConfig;
+
+public class App2 {
+
+ public static void main(String[] args) {
+ ServerConfig cfg = new ServerConfig();
+ cfg.setDefaultServer(true);
+ Properties properties = new Properties();
+ properties.put("ebean.db.ddl.generate", "true");
+ properties.put("ebean.db.ddl.run", "true");
+ properties.put("datasource.db.username", "sa");
+ properties.put("datasource.db.password", "");
+ properties.put("datasource.db.databaseUrl", "jdbc:h2:mem:app2");
+ properties.put("datasource.db.databaseDriver", "org.h2.Driver");
+ cfg.loadFromProperties(properties);
+ EbeanServer server = EbeanServerFactory.create(cfg);
+
+ }
+
+}
diff --git a/libraries-data/src/main/java/com/baeldung/ebean/model/Address.java b/libraries-data/src/main/java/com/baeldung/ebean/model/Address.java
new file mode 100644
index 0000000000..dfcd90ffa7
--- /dev/null
+++ b/libraries-data/src/main/java/com/baeldung/ebean/model/Address.java
@@ -0,0 +1,48 @@
+package com.baeldung.ebean.model;
+
+import javax.persistence.Entity;
+
+@Entity
+public class Address extends BaseModel {
+
+ public Address(String addressLine1, String addressLine2, String city) {
+ super();
+ this.addressLine1 = addressLine1;
+ this.addressLine2 = addressLine2;
+ this.city = city;
+ }
+
+ private String addressLine1;
+ private String addressLine2;
+ private String city;
+
+ public String getAddressLine1() {
+ return addressLine1;
+ }
+
+ public void setAddressLine1(String addressLine1) {
+ this.addressLine1 = addressLine1;
+ }
+
+ public String getAddressLine2() {
+ return addressLine2;
+ }
+
+ public void setAddressLine2(String addressLine2) {
+ this.addressLine2 = addressLine2;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ @Override
+ public String toString() {
+ return "Address [id=" + id + ", addressLine1=" + addressLine1 + ", addressLine2=" + addressLine2 + ", city=" + city + "]";
+ }
+
+}
diff --git a/libraries-data/src/main/java/com/baeldung/ebean/model/BaseModel.java b/libraries-data/src/main/java/com/baeldung/ebean/model/BaseModel.java
new file mode 100644
index 0000000000..547d5bf075
--- /dev/null
+++ b/libraries-data/src/main/java/com/baeldung/ebean/model/BaseModel.java
@@ -0,0 +1,59 @@
+package com.baeldung.ebean.model;
+
+import java.time.Instant;
+
+import javax.persistence.Id;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.Version;
+
+import io.ebean.annotation.WhenCreated;
+import io.ebean.annotation.WhenModified;
+
+@MappedSuperclass
+public abstract class BaseModel {
+
+ @Id
+ protected long id;
+
+ @Version
+ protected long version;
+
+ @WhenCreated
+ protected Instant createdOn;
+
+ @WhenModified
+ protected Instant modifiedOn;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Instant getCreatedOn() {
+ return createdOn;
+ }
+
+ public void setCreatedOn(Instant createdOn) {
+ this.createdOn = createdOn;
+ }
+
+ public Instant getModifiedOn() {
+ return modifiedOn;
+ }
+
+ public void setModifiedOn(Instant modifiedOn) {
+ this.modifiedOn = modifiedOn;
+ }
+
+ public long getVersion() {
+ return version;
+ }
+
+ public void setVersion(long version) {
+ this.version = version;
+ }
+
+}
diff --git a/libraries-data/src/main/java/com/baeldung/ebean/model/Customer.java b/libraries-data/src/main/java/com/baeldung/ebean/model/Customer.java
new file mode 100644
index 0000000000..4dd629245a
--- /dev/null
+++ b/libraries-data/src/main/java/com/baeldung/ebean/model/Customer.java
@@ -0,0 +1,42 @@
+package com.baeldung.ebean.model;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.OneToOne;
+
+@Entity
+public class Customer extends BaseModel {
+
+ public Customer(String name, Address address) {
+ super();
+ this.name = name;
+ this.address = address;
+ }
+
+ private String name;
+
+ @OneToOne(cascade = CascadeType.ALL)
+ Address address;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Address getAddress() {
+ return address;
+ }
+
+ public void setAddress(Address address) {
+ this.address = address;
+ }
+
+ @Override
+ public String toString() {
+ return "Customer [id=" + id + ", name=" + name + ", address=" + address + "]";
+ }
+
+}
diff --git a/libraries-data/src/main/resources/ebean.mf b/libraries-data/src/main/resources/ebean.mf
new file mode 100644
index 0000000000..f49fecc717
--- /dev/null
+++ b/libraries-data/src/main/resources/ebean.mf
@@ -0,0 +1,3 @@
+entity-packages: com.baeldung.ebean.model
+transactional-packages: com.baeldung.ebean.app
+querybean-packages: com.baeldung.ebean.app
diff --git a/libraries-data/src/main/resources/ebean.properties b/libraries-data/src/main/resources/ebean.properties
new file mode 100644
index 0000000000..9cc5cc170a
--- /dev/null
+++ b/libraries-data/src/main/resources/ebean.properties
@@ -0,0 +1,7 @@
+ebean.db.ddl.generate=true
+ebean.db.ddl.run=true
+
+datasource.db.username=sa
+datasource.db.password=
+datasource.db.databaseUrl=jdbc:h2:mem:customer
+datasource.db.databaseDriver=org.h2.Driver
diff --git a/libraries-data/src/main/resources/logback.xml b/libraries-data/src/main/resources/logback.xml
index 7d900d8ea8..a57d22fcb2 100644
--- a/libraries-data/src/main/resources/logback.xml
+++ b/libraries-data/src/main/resources/logback.xml
@@ -6,7 +6,9 @@
-
+
+
+
diff --git a/maven/versions-maven-plugin/original/pom.xml b/maven/versions-maven-plugin/original/pom.xml
new file mode 100644
index 0000000000..295c77b860
--- /dev/null
+++ b/maven/versions-maven-plugin/original/pom.xml
@@ -0,0 +1,76 @@
+
+ 4.0.0
+ com.baeldung
+ versions-maven-plugin-example
+ 0.0.1-SNAPSHOT
+
+
+ 1.15
+
+
+
+
+
+ commons-io
+ commons-io
+ 2.3
+
+
+
+ org.apache.commons
+ commons-collections4
+ 4.0
+
+
+
+ org.apache.commons
+ commons-lang3
+ 3.0
+
+
+
+ org.apache.commons
+ commons-compress
+ ${commons-compress-version}
+
+
+
+ commons-beanutils
+ commons-beanutils
+ 1.9.1-SNAPSHOT
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ versions-maven-plugin
+ 2.7
+
+
+ org.apache.commons:commons-collections4
+
+
+
+
+
+
+
+
+ apache.snapshots
+ Apache Development Snapshot Repository
+ https://repository.apache.org/content/repositories/snapshots/
+
+ false
+
+
+ true
+
+
+
+
+
\ No newline at end of file
diff --git a/maven/versions-maven-plugin/pom.xml b/maven/versions-maven-plugin/pom.xml
new file mode 100644
index 0000000000..295c77b860
--- /dev/null
+++ b/maven/versions-maven-plugin/pom.xml
@@ -0,0 +1,76 @@
+
+ 4.0.0
+ com.baeldung
+ versions-maven-plugin-example
+ 0.0.1-SNAPSHOT
+
+
+ 1.15
+
+
+
+
+
+ commons-io
+ commons-io
+ 2.3
+
+
+
+ org.apache.commons
+ commons-collections4
+ 4.0
+
+
+
+ org.apache.commons
+ commons-lang3
+ 3.0
+
+
+
+ org.apache.commons
+ commons-compress
+ ${commons-compress-version}
+
+
+
+ commons-beanutils
+ commons-beanutils
+ 1.9.1-SNAPSHOT
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ versions-maven-plugin
+ 2.7
+
+
+ org.apache.commons:commons-collections4
+
+
+
+
+
+
+
+
+ apache.snapshots
+ Apache Development Snapshot Repository
+ https://repository.apache.org/content/repositories/snapshots/
+
+ false
+
+
+ true
+
+
+
+
+
\ No newline at end of file
diff --git a/maven/versions-maven-plugin/run-the-demo.sh b/maven/versions-maven-plugin/run-the-demo.sh
new file mode 100755
index 0000000000..89ca871e01
--- /dev/null
+++ b/maven/versions-maven-plugin/run-the-demo.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+#function to display commands
+exe() { echo -e "\$ $@\n" ; "$@" ; }
+
+TEXT_COLOR='\033[1;33m' #Yellow
+NO_COLOR='\033[0m' # No Color
+
+clear
+
+echo -e "======================================================================================"
+echo -e " Showcase for the BAELDUNG tutorial \"Use the latest version of a dependency in Maven\""
+echo -e " Author: Andrea Ligios"
+echo -e "======================================================================================"
+
+echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
+echo -e " Resetting the demo environment (which will be altered during the run): "
+echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
+rm -f pom.xml.versionsBackup
+cp original/pom.xml pom.xml
+ls -lt pom.*
+echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
+echo -e " Checking for newer versions of the Maven dependencies:"
+echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
+exe mvn versions:display-dependency-updates
+echo
+read -p "Press enter to continue"
+
+echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
+echo -e " Updating SNAPSHOT dependencies to their RELEASE version, if any:"
+echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
+exe mvn versions:use-releases
+echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
+echo -e " A backup has been created automatically:"
+echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
+ls -lt pom.*
+echo
+read -p "Press enter to continue"
+
+echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
+echo -e " Updating RELEASE dependencies to their *next* RELEASE version:"
+echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
+exe mvn versions:use-next-releases
+echo
+read -p "Press enter to continue"
+
+echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
+echo -e " Reverting every modification made since the beginning:"
+echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
+exe mvn versions:revert
+echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
+echo -e " The backup is gone, and the pom.xml contains the initial dependencies:"
+echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
+ls -lt pom.*
+echo
+read -p "Press enter to continue"
+
+echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
+echo -e " Updating RELEASE dependencies to their *latest* RELEASE version:"
+echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
+exe mvn versions:use-latest-releases
+echo
+read -p "Press enter to continue"
+
+echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
+echo -e " Committing the modifications to pom.xml:"
+echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
+exe mvn versions:commit
+echo -e "${TEXT_COLOR}\n--------------------------------------------------------------------------------------"
+echo -e " The backup is gone, and the pom.xml contains the latest dependencies:"
+echo -e "--------------------------------------------------------------------------------------${NO_COLOR}"
+ls -lt pom.*
+echo
+
+echo -e "${TEXT_COLOR}\nThat's all folks!${NO_COLOR}\n"
diff --git a/pom.xml b/pom.xml
index a499aac7ee..6c77ede1c2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -399,6 +399,7 @@
javafx
jgroups
jee-7
+ jee-7-security
jhipster
jjwt
jsf
@@ -526,31 +527,6 @@
spring-resttemplate
- spring-security-acl
- spring-security-cache-control
- spring-security-client/spring-security-jsp-authentication
- spring-security-client/spring-security-jsp-authorize
- spring-security-client/spring-security-jsp-config
- spring-security-client/spring-security-mvc
- spring-security-client/spring-security-thymeleaf-authentication
- spring-security-client/spring-security-thymeleaf-authorize
- spring-security-client/spring-security-thymeleaf-config
- spring-security-core
- spring-security-mvc-boot
- spring-security-mvc-custom
- spring-security-mvc-digest-auth
- spring-security-mvc-ldap
- spring-security-mvc-login
- spring-security-mvc-persisted-remember-me
- spring-security-mvc-session
- spring-security-mvc-socket
- spring-security-openid
-
- spring-security-rest-basic-auth
- spring-security-rest-custom
- spring-security-rest
- spring-security-sso
- spring-security-x509
@@ -665,7 +641,6 @@
dubbo
flyway
- java-difference-date
jni
jooby
@@ -720,7 +695,33 @@
- flyway-cdi-extension
+ flyway-cdi-extension
+
+ spring-security-acl
+ spring-security-cache-control
+ spring-security-client/spring-security-jsp-authentication
+ spring-security-client/spring-security-jsp-authorize
+ spring-security-client/spring-security-jsp-config
+ spring-security-client/spring-security-mvc
+ spring-security-client/spring-security-thymeleaf-authentication
+ spring-security-client/spring-security-thymeleaf-authorize
+ spring-security-client/spring-security-thymeleaf-config
+ spring-security-core
+ spring-security-mvc-boot
+ spring-security-mvc-custom
+ spring-security-mvc-digest-auth
+ spring-security-mvc-ldap
+ spring-security-mvc-login
+ spring-security-mvc-persisted-remember-me
+ spring-security-mvc-session
+ spring-security-mvc-socket
+ spring-security-openid
+
+ spring-security-rest-basic-auth
+ spring-security-rest-custom
+ spring-security-rest
+ spring-security-sso
+ spring-security-x509
@@ -1138,7 +1139,6 @@
dubbo
flyway
- java-difference-date
jni
jooby
@@ -1303,6 +1303,7 @@
javafx
jgroups
jee-7
+ jee-7-security
jjwt
jsf
json-path
diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index ad70d987bb..072ed7a2ac 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -34,6 +34,12 @@
${mongodb-reactivestreams.version}
+
+ io.projectreactor
+ reactor-core
+ ${projectreactor.version}
+
+
io.projectreactor
reactor-test
@@ -109,6 +115,7 @@
5.1.0.RELEASE
1.9.2
3.2.0.RELEASE
+
diff --git a/xml/src/main/java/com/baeldung/xml/XMLDocumentWriter.java b/xml/src/main/java/com/baeldung/xml/XMLDocumentWriter.java
new file mode 100644
index 0000000000..e33fc5fe1d
--- /dev/null
+++ b/xml/src/main/java/com/baeldung/xml/XMLDocumentWriter.java
@@ -0,0 +1,41 @@
+package com.baeldung.xml;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.w3c.dom.Document;
+
+public class XMLDocumentWriter {
+
+ public void write(Document document, String fileName, boolean excludeDeclaration, boolean prettyPrint) {
+ try(FileWriter writer = new FileWriter(new File(fileName))) {
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ Transformer transformer = transformerFactory.newTransformer();
+ if(excludeDeclaration) {
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+ }
+ if(prettyPrint) {
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
+ }
+ DOMSource source = new DOMSource(document);
+ StreamResult result = new StreamResult(writer);
+ transformer.transform(source, result);
+ } catch (IOException e) {
+ throw new IllegalArgumentException(e);
+ } catch (TransformerConfigurationException e) {
+ throw new IllegalStateException(e);
+ } catch (TransformerException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+}
diff --git a/xml/src/test/java/com/baeldung/xml/XMLDocumentWriterUnitTest.java b/xml/src/test/java/com/baeldung/xml/XMLDocumentWriterUnitTest.java
new file mode 100644
index 0000000000..68f787a054
--- /dev/null
+++ b/xml/src/test/java/com/baeldung/xml/XMLDocumentWriterUnitTest.java
@@ -0,0 +1,52 @@
+package com.baeldung.xml;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.After;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.io.File;
+
+public class XMLDocumentWriterUnitTest {
+
+ @Test
+ public void givenXMLDocumentWhenWriteIsCalledThenXMLIsWrittenToFile() throws Exception {
+ Document document = createSampleDocument();
+ new XMLDocumentWriter().write(document, "company_simple.xml", false, false);
+ }
+
+ @Test
+ public void givenXMLDocumentWhenWriteIsCalledWithPrettyPrintThenFormattedXMLIsWrittenToFile() throws Exception {
+ Document document = createSampleDocument();
+ new XMLDocumentWriter().write(document, "company_prettyprinted.xml", false, true);
+ }
+
+ private Document createSampleDocument() throws ParserConfigurationException {
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+ Document document = documentBuilder.newDocument();
+ Element companyElement = document.createElement("Company");
+ document.appendChild(companyElement);
+ Element departmentElement = document.createElement("Department");
+ departmentElement.setAttribute("name", "Sales");
+ companyElement.appendChild(departmentElement);
+ Element employee1 = document.createElement("Employee");
+ employee1.setAttribute("name", "John Smith");
+ departmentElement.appendChild(employee1);
+ Element employee2 = document.createElement("Employee");
+ employee2.setAttribute("name", "Tim Dellor");
+ departmentElement.appendChild(employee2);
+ return document;
+ }
+
+ @After
+ public void cleanUp() throws Exception {
+ FileUtils.deleteQuietly(new File("company_simple.xml"));
+ FileUtils.deleteQuietly(new File("company_prettyprinted.xml"));
+ }
+}