diff --git a/algorithms-miscellaneous-2/README.md b/algorithms-miscellaneous-2/README.md
index de054566ed..462644dddb 100644
--- a/algorithms-miscellaneous-2/README.md
+++ b/algorithms-miscellaneous-2/README.md
@@ -15,3 +15,5 @@
- [Calculate Percentage in Java](https://www.baeldung.com/java-calculate-percentage)
- [Converting Between Byte Arrays and Hexadecimal Strings in Java](https://www.baeldung.com/java-byte-arrays-hex-strings)
- [Convert Latitude and Longitude to a 2D Point in Java](https://www.baeldung.com/java-convert-latitude-longitude)
+- [Reversing a Binary Tree in Java](https://www.baeldung.com/java-reversing-a-binary-tree)
+- [Find If Two Numbers Are Relatively Prime in Java](https://www.baeldung.com/java-two-relatively-prime-numbers)
diff --git a/algorithms-miscellaneous-3/README.md b/algorithms-miscellaneous-3/README.md
index f299492d9c..4dd4b66ff2 100644
--- a/algorithms-miscellaneous-3/README.md
+++ b/algorithms-miscellaneous-3/README.md
@@ -4,4 +4,3 @@
- [Implementing Simple State Machines with Java Enums](https://www.baeldung.com/java-enum-simple-state-machine)
- [Converting Between Roman and Arabic Numerals in Java](http://www.baeldung.com/java-convert-roman-arabic)
- [Practical Java Examples of the Big O Notation](http://www.baeldung.com/java-algorithm-complexity)
-- [An Introduction to the Theory of Big-O Notation](http://www.baeldung.com/big-o-notation)
\ No newline at end of file
diff --git a/core-groovy-2/README.md b/core-groovy-2/README.md
index f60bdb3cbe..c8df242e1a 100644
--- a/core-groovy-2/README.md
+++ b/core-groovy-2/README.md
@@ -3,5 +3,5 @@
## Relevant articles:
- [String Matching in Groovy](http://www.baeldung.com/)
-- [Groovy def Keyword]
-
+- [Groovy def Keyword](https://www.baeldung.com/groovy-def-keyword)
+- [Pattern Matching in Strings in Groovy](https://www.baeldung.com/groovy-pattern-matching)
diff --git a/core-groovy-2/src/main/resources/articleEmail.template b/core-groovy-2/src/main/resources/articleEmail.template
new file mode 100644
index 0000000000..26488f6288
--- /dev/null
+++ b/core-groovy-2/src/main/resources/articleEmail.template
@@ -0,0 +1,5 @@
+Dear <% out << (user) %>,
+Please read the requested article below.
+<% out << (articleText) %>
+From,
+<% out << (signature) %>
\ No newline at end of file
diff --git a/core-groovy-2/src/main/resources/email.template b/core-groovy-2/src/main/resources/email.template
new file mode 100644
index 0000000000..fe4eaff851
--- /dev/null
+++ b/core-groovy-2/src/main/resources/email.template
@@ -0,0 +1,3 @@
+Dear $user,
+Thanks for subscribing our services.
+${signature}
\ No newline at end of file
diff --git a/core-groovy-2/src/test/groovy/com/baeldung/templateengine/TemplateEnginesUnitTest.groovy b/core-groovy-2/src/test/groovy/com/baeldung/templateengine/TemplateEnginesUnitTest.groovy
new file mode 100644
index 0000000000..1846ae664c
--- /dev/null
+++ b/core-groovy-2/src/test/groovy/com/baeldung/templateengine/TemplateEnginesUnitTest.groovy
@@ -0,0 +1,96 @@
+package com.baeldung.templateengine
+
+import groovy.text.SimpleTemplateEngine
+import groovy.text.StreamingTemplateEngine
+import groovy.text.GStringTemplateEngine
+import groovy.text.XmlTemplateEngine
+import groovy.text.XmlTemplateEngine
+import groovy.text.markup.MarkupTemplateEngine
+import groovy.text.markup.TemplateConfiguration
+
+class TemplateEnginesUnitTest extends GroovyTestCase {
+
+ def bindMap = [user: "Norman", signature: "Baeldung"]
+
+ void testSimpleTemplateEngine() {
+ def smsTemplate = 'Dear <% print user %>, Thanks for reading our Article. ${signature}'
+ def smsText = new SimpleTemplateEngine().createTemplate(smsTemplate).make(bindMap)
+
+ assert smsText.toString() == "Dear Norman, Thanks for reading our Article. Baeldung"
+ }
+
+ void testStreamingTemplateEngine() {
+ def articleEmailTemplate = new File('src/main/resources/articleEmail.template')
+ bindMap.articleText = """1. Overview
+This is a tutorial article on Template Engines""" //can be a string larger than 64k
+
+ def articleEmailText = new StreamingTemplateEngine().createTemplate(articleEmailTemplate).make(bindMap)
+
+ assert articleEmailText.toString() == """Dear Norman,
+Please read the requested article below.
+1. Overview
+This is a tutorial article on Template Engines
+From,
+Baeldung"""
+
+ }
+
+ void testGStringTemplateEngine() {
+ def emailTemplate = new File('src/main/resources/email.template')
+ def emailText = new GStringTemplateEngine().createTemplate(emailTemplate).make(bindMap)
+
+ assert emailText.toString() == "Dear Norman,\nThanks for subscribing our services.\nBaeldung"
+ }
+
+ void testXmlTemplateEngine() {
+ def emailXmlTemplate = '''
+ def emailContent = "Thanks for subscribing our services."
+
+ Dear ${user}
+ emailContent
+ ${signature}
+
+ '''
+ def emailXml = new XmlTemplateEngine().createTemplate(emailXmlTemplate).make(bindMap)
+ println emailXml.toString()
+ }
+
+ void testMarkupTemplateEngineHtml() {
+ def emailHtmlTemplate = """html {
+ head {
+ title('Service Subscription Email')
+ }
+ body {
+ p('Dear Norman')
+ p('Thanks for subscribing our services.')
+ p('Baeldung')
+ }
+ }"""
+
+
+ def emailHtml = new MarkupTemplateEngine().createTemplate(emailHtmlTemplate).make()
+ println emailHtml.toString()
+
+ }
+
+ void testMarkupTemplateEngineXml() {
+ def emailXmlTemplate = """xmlDeclaration()
+ xs{
+ email {
+ greet('Dear Norman')
+ content('Thanks for subscribing our services.')
+ signature('Baeldung')
+ }
+ }
+ """
+ TemplateConfiguration config = new TemplateConfiguration()
+ config.autoIndent = true
+ config.autoEscape = true
+ config.autoNewLine = true
+
+ def emailXml = new MarkupTemplateEngine(config).createTemplate(emailXmlTemplate).make()
+
+ println emailXml.toString()
+ }
+
+}
\ No newline at end of file
diff --git a/core-groovy-collections/README.md b/core-groovy-collections/README.md
index 482e33bce1..aeba8933be 100644
--- a/core-groovy-collections/README.md
+++ b/core-groovy-collections/README.md
@@ -2,5 +2,5 @@
## Relevant articles:
-- [Maps in Groovy](http://www.baeldung.com/)
+- [Maps in Groovy](https://www.baeldung.com/groovy-maps)
diff --git a/core-java-arrays/README.MD b/core-java-arrays/README.MD
new file mode 100644
index 0000000000..9ee6998784
--- /dev/null
+++ b/core-java-arrays/README.MD
@@ -0,0 +1,3 @@
+## Relevant Articles
+
+- [Extending an Array’s Length](https://www.baeldung.com/java-array-add-element-at-the-end)
diff --git a/core-java-arrays/src/main/java/com/baeldung/array/conversions/StreamArrayConversion.java b/core-java-arrays/src/main/java/com/baeldung/array/conversions/StreamArrayConversion.java
new file mode 100644
index 0000000000..26a4ca7ef4
--- /dev/null
+++ b/core-java-arrays/src/main/java/com/baeldung/array/conversions/StreamArrayConversion.java
@@ -0,0 +1,52 @@
+package com.baeldung.array.conversions;
+
+import java.util.Arrays;
+import java.util.function.IntFunction;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+public class StreamArrayConversion {
+
+ public static String[] stringStreamToStringArrayUsingFunctionalInterface(Stream stringStream) {
+ IntFunction intFunction = new IntFunction() {
+ @Override
+ public String[] apply(int value) {
+ return new String[value];
+ }
+ };
+
+ return stringStream.toArray(intFunction);
+ }
+
+ public static String[] stringStreamToStringArrayUsingMethodReference(Stream stringStream) {
+ return stringStream.toArray(String[]::new);
+ }
+
+ public static String[] stringStreamToStringArrayUsingLambda(Stream stringStream) {
+ return stringStream.toArray(value -> new String[value]);
+ }
+
+ public static Integer[] integerStreamToIntegerArray(Stream integerStream) {
+ return integerStream.toArray(Integer[]::new);
+ }
+
+ public static int[] intStreamToPrimitiveIntArray(Stream integerStream) {
+ return integerStream.mapToInt(i -> i).toArray();
+ }
+
+ public static Stream stringArrayToStreamUsingArraysStream(String[] stringArray) {
+ return Arrays.stream(stringArray);
+ }
+
+ public static Stream stringArrayToStreamUsingStreamOf(String[] stringArray) {
+ return Stream.of(stringArray);
+ }
+
+ public static IntStream primitiveIntArrayToStreamUsingArraysStream(int[] intArray) {
+ return Arrays.stream(intArray);
+ }
+
+ public static Stream primitiveIntArrayToStreamUsingStreamOf(int[] intArray) {
+ return Stream.of(intArray);
+ }
+}
diff --git a/core-java-arrays/src/test/java/com/baeldung/array/conversions/StreamArrayConversionUnitTest.java b/core-java-arrays/src/test/java/com/baeldung/array/conversions/StreamArrayConversionUnitTest.java
new file mode 100644
index 0000000000..d2173fea5b
--- /dev/null
+++ b/core-java-arrays/src/test/java/com/baeldung/array/conversions/StreamArrayConversionUnitTest.java
@@ -0,0 +1,70 @@
+package com.baeldung.array.conversions;
+
+import static com.baeldung.array.conversions.StreamArrayConversion.intStreamToPrimitiveIntArray;
+import static com.baeldung.array.conversions.StreamArrayConversion.integerStreamToIntegerArray;
+import static com.baeldung.array.conversions.StreamArrayConversion.stringStreamToStringArrayUsingFunctionalInterface;
+import static com.baeldung.array.conversions.StreamArrayConversion.stringStreamToStringArrayUsingLambda;
+import static com.baeldung.array.conversions.StreamArrayConversion.stringStreamToStringArrayUsingMethodReference;
+import static com.baeldung.array.conversions.StreamArrayConversion.stringArrayToStreamUsingArraysStream;
+import static com.baeldung.array.conversions.StreamArrayConversion.stringArrayToStreamUsingStreamOf;
+import static com.baeldung.array.conversions.StreamArrayConversion.primitiveIntArrayToStreamUsingArraysStream;
+import static com.baeldung.array.conversions.StreamArrayConversion.primitiveIntArrayToStreamUsingStreamOf;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.Iterators;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+import org.junit.Test;
+
+public class StreamArrayConversionUnitTest {
+
+ private String[] stringArray = new String[]{"baeldung", "convert", "to", "string", "array"};
+ private Integer[] integerArray = new Integer[]{1, 2, 3, 4, 5, 6, 7};
+ private int[] intPrimitiveArray = new int[]{1, 2, 3, 4, 5, 6, 7};
+
+ @Test
+ public void givenStringStream_thenConvertToStringArrayUsingFunctionalInterface() {
+ Stream stringStream = Stream.of("baeldung", "convert", "to", "string", "array");
+ assertArrayEquals(stringArray, stringStreamToStringArrayUsingFunctionalInterface(stringStream));
+ }
+
+ @Test
+ public void givenStringStream_thenConvertToStringArrayUsingMethodReference() {
+ Stream stringStream = Stream.of("baeldung", "convert", "to", "string", "array");
+ assertArrayEquals(stringArray, stringStreamToStringArrayUsingMethodReference(stringStream));
+ }
+
+ @Test
+ public void givenStringStream_thenConvertToStringArrayUsingLambda() {
+ Stream stringStream = Stream.of("baeldung", "convert", "to", "string", "array");
+ assertArrayEquals(stringArray, stringStreamToStringArrayUsingLambda(stringStream));
+ }
+
+ @Test
+ public void givenIntegerStream_thenConvertToIntegerArray() {
+ Stream integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7);
+ assertArrayEquals(integerArray, integerStreamToIntegerArray(integerStream));
+ }
+
+ @Test
+ public void givenIntStream_thenConvertToIntegerArray() {
+ Stream integerStream = IntStream.rangeClosed(1, 7).boxed();
+ assertArrayEquals(intPrimitiveArray, intStreamToPrimitiveIntArray(integerStream));
+ }
+
+ @Test
+ public void givenStringArray_whenConvertedTwoWays_thenConvertedStreamsAreEqual() {
+ assertTrue(Iterators
+ .elementsEqual(stringArrayToStreamUsingArraysStream(stringArray).iterator(),
+ stringArrayToStreamUsingStreamOf(stringArray).iterator()));
+ }
+
+ @Test
+ public void givenPrimitiveArray_whenConvertedTwoWays_thenConvertedStreamsAreNotEqual() {
+ assertFalse(Iterators.elementsEqual(
+ primitiveIntArrayToStreamUsingArraysStream(intPrimitiveArray).iterator(),
+ primitiveIntArrayToStreamUsingStreamOf(intPrimitiveArray).iterator()));
+ }
+}
diff --git a/core-java-lambdas/README.md b/core-java-lambdas/README.md
new file mode 100644
index 0000000000..5b94953e68
--- /dev/null
+++ b/core-java-lambdas/README.md
@@ -0,0 +1,2 @@
+### Relevant Articles:
+- [Java 9 java.lang.Module API](https://www.baeldung.com/java-lambda-effectively-final-local-variables)
diff --git a/core-java-modules/core-java-11/README.md b/core-java-modules/core-java-11/README.md
index a4b0e0e59c..d68a1c87eb 100644
--- a/core-java-modules/core-java-11/README.md
+++ b/core-java-modules/core-java-11/README.md
@@ -7,3 +7,4 @@
- [Exploring the New HTTP Client in Java 9 and 11](https://www.baeldung.com/java-9-http-client)
- [An Introduction to Epsilon GC: A No-Op Experimental Garbage Collector](https://www.baeldung.com/jvm-epsilon-gc-garbage-collector)
- [Guide to jlink](https://www.baeldung.com/jlink)
+- [Transforming an Empty String into an Empty Optional](https://www.baeldung.com/java-empty-string-to-empty-optional)
diff --git a/core-java-modules/core-java-8-2/README.md b/core-java-modules/core-java-8-2/README.md
index e2b12e8819..383fe5da34 100644
--- a/core-java-modules/core-java-8-2/README.md
+++ b/core-java-modules/core-java-8-2/README.md
@@ -3,4 +3,5 @@
## Core Java 8 Cookbooks and Examples (part 2)
### Relevant Articles:
-- [Anonymous Classes in Java](http://www.baeldung.com/)
+- [Anonymous Classes in Java](https://www.baeldung.com/java-anonymous-classes)
+- [Run JAR Application With Command Line Arguments](https://www.baeldung.com/java-run-jar-with-arguments)
diff --git a/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalChainingUnitTest.java b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalChainingUnitTest.java
index 70ec324cb3..3e0d752bb6 100644
--- a/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalChainingUnitTest.java
+++ b/core-java-modules/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalChainingUnitTest.java
@@ -101,7 +101,7 @@ public class OptionalChainingUnitTest {
}
private Optional createOptional(String input) {
- if (input == null || input == "" || input == "empty") {
+ if (input == null || "".equals(input) || "empty".equals(input)) {
return Optional.empty();
}
diff --git a/core-java-modules/core-java-9/README.md b/core-java-modules/core-java-9/README.md
index 8fdc3f6ee2..5715520bae 100644
--- a/core-java-modules/core-java-9/README.md
+++ b/core-java-modules/core-java-9/README.md
@@ -20,6 +20,14 @@
- [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar)
- [Ahead of Time Compilation (AoT)](https://www.baeldung.com/ahead-of-time-compilation)
- [Java 9 Process API Improvements](https://www.baeldung.com/java-9-process-api)
-- [Guide to java.lang.Process API](https://www.baeldung.com/java-process-api)
-
-
+- [Java 9 java.util.Objects Additions](https://www.baeldung.com/java-9-objects-new)
+- [Java 9 Reactive Streams](https://www.baeldung.com/java-9-reactive-streams)
+- [Java 9 Optional API Additions](https://www.baeldung.com/java-9-optional)
+- [Java 9 CompletableFuture API Improvements](https://www.baeldung.com/java-9-completablefuture)
+- [Introduction to Java 9 StackWalking API](https://www.baeldung.com/java-9-stackwalking-api)
+- [Java 9 Convenience Factory Methods for Collections](https://www.baeldung.com/java-9-collections-factory-methods)
+- [Java 9 Stream API Improvements](https://www.baeldung.com/java-9-stream-api)
+- [A Guide to Java 9 Modularity](https://www.baeldung.com/java-9-modularity)
+- [Java 9 Platform Module API](https://www.baeldung.com/java-9-module-api)
+- [Java 9 Platform Logging API](https://www.baeldung.com/java-9-logging-api)
+- [Filtering a Stream of Optionals in Java](https://www.baeldung.com/java-filter-stream-of-optional)
diff --git a/core-java-modules/core-java-collections-set/README.md b/core-java-modules/core-java-collections-set/README.md
index 217e9ee6a5..2e09e920dc 100644
--- a/core-java-modules/core-java-collections-set/README.md
+++ b/core-java-modules/core-java-collections-set/README.md
@@ -8,4 +8,5 @@
- [A Guide to HashSet in Java](http://www.baeldung.com/java-hashset)
- [A Guide to TreeSet in Java](http://www.baeldung.com/java-tree-set)
- [Initializing HashSet at the Time of Construction](http://www.baeldung.com/java-initialize-hashset)
-- [Guide to EnumSet](https://www.baeldung.com/java-enumset)
\ No newline at end of file
+- [Guide to EnumSet](https://www.baeldung.com/java-enumset)
+- [Set Operations in Java](https://www.baeldung.com/java-set-operations)
diff --git a/core-java-modules/core-java-exceptions/pom.xml b/core-java-modules/core-java-exceptions/pom.xml
new file mode 100644
index 0000000000..51c4e51341
--- /dev/null
+++ b/core-java-modules/core-java-exceptions/pom.xml
@@ -0,0 +1,26 @@
+
+ 4.0.0
+ com.baeldung.exception.numberformat
+ core-java-exceptions
+ 0.0.1-SNAPSHOT
+ core-java-exceptions
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../../parent-java
+
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+
+
diff --git a/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exception/numberformat/NumberFormatExceptionUnitTest.java b/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exception/numberformat/NumberFormatExceptionUnitTest.java
new file mode 100644
index 0000000000..a1e8c7c30f
--- /dev/null
+++ b/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exception/numberformat/NumberFormatExceptionUnitTest.java
@@ -0,0 +1,154 @@
+package com.baeldung.exception.numberformat;
+
+import static org.junit.Assert.assertEquals;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.Locale;
+import java.util.logging.Logger;
+
+import org.junit.Test;
+
+/**
+ * A set of examples tested to show cases where NumberFormatException is thrown and not thrown.
+ */
+public class NumberFormatExceptionUnitTest {
+
+ Logger LOG = Logger.getLogger(NumberFormatExceptionUnitTest.class.getName());
+
+ /* ---INTEGER FAIL CASES--- */
+ @Test(expected = NumberFormatException.class)
+ public void givenByteConstructor_whenAlphabetAsInput_thenFail() {
+ Byte byteInt = new Byte("one");
+ }
+
+ @Test(expected = NumberFormatException.class)
+ public void givenShortConstructor_whenSpaceInInput_thenFail() {
+ Short shortInt = new Short("2 ");
+ }
+
+ @Test(expected = NumberFormatException.class)
+ public void givenParseIntMethod_whenSpaceInInput_thenFail() {
+ Integer aIntPrim = Integer.parseInt("6000 ");
+ }
+
+ @Test(expected = NumberFormatException.class)
+ public void givenParseIntMethod_whenUnderscoreInInput_thenFail() {
+ int bIntPrim = Integer.parseInt("6_000");
+ }
+
+ @Test(expected = NumberFormatException.class)
+ public void givenIntegerValueOfMethod_whenCommaInInput_thenFail() {
+ Integer cIntPrim = Integer.valueOf("6,000");
+ }
+
+ @Test(expected = NumberFormatException.class)
+ public void givenBigIntegerConstructor_whenDecimalInInput_thenFail() {
+ BigInteger bigInteger = new BigInteger("4.0");
+ }
+
+ @Test(expected = NumberFormatException.class)
+ public void givenDecodeMethod_whenAlphabetInInput_thenFail() {
+ Long decodeInteger = Long.decode("64403L");
+ }
+
+ /* ---INTEGER PASS CASES--- */
+ @Test
+ public void givenInvalidNumberInputs_whenOptimized_thenPass() {
+ Byte byteInt = new Byte("1");
+ assertEquals(1, byteInt.intValue());
+
+ Short shortInt = new Short("2 ".trim());
+ assertEquals(2, shortInt.intValue());
+
+ Integer aIntObj = Integer.valueOf("6");
+ assertEquals(6, aIntObj.intValue());
+
+ BigInteger bigInteger = new BigInteger("4");
+ assertEquals(4, bigInteger.intValue());
+
+ int aIntPrim = Integer.parseInt("6000 ".trim());
+ assertEquals(6000, aIntPrim);
+
+ int bIntPrim = Integer.parseInt("6_000".replaceAll("_", ""));
+ assertEquals(6000, bIntPrim);
+
+ int cIntPrim = Integer.parseInt("-6000");
+ assertEquals(-6000, cIntPrim);
+
+ Long decodeInteger = Long.decode("644032334");
+ assertEquals(644032334L, decodeInteger.longValue());
+ }
+
+ /* ---DOUBLE FAIL CASES--- */
+ @Test(expected = NumberFormatException.class)
+ public void givenFloatConstructor_whenAlphabetInInput_thenFail() {
+ Float floatDecimalObj = new Float("one.1");
+ }
+
+ @Test(expected = NumberFormatException.class)
+ public void givenDoubleConstructor_whenAlphabetInInput_thenFail() {
+ Double doubleDecimalObj = new Double("two.2");
+ }
+
+ @Test(expected = NumberFormatException.class)
+ public void givenBigDecimalConstructor_whenSpecialCharsInInput_thenFail() {
+ BigDecimal bigDecimalObj = new BigDecimal("3_0.3");
+ }
+
+ @Test(expected = NumberFormatException.class)
+ public void givenParseDoubleMethod_whenCommaInInput_thenFail() {
+ double aDoublePrim = Double.parseDouble("4000,1");
+ }
+
+ /* ---DOUBLE PASS CASES--- */
+ @Test
+ public void givenDoubleConstructor_whenDecimalInInput_thenPass() {
+ Double doubleDecimalObj = new Double("2.2");
+ assertEquals(2.2, doubleDecimalObj.doubleValue(), 0);
+ }
+
+ @Test
+ public void givenDoubleValueOfMethod_whenMinusInInput_thenPass() {
+ Double aDoubleObj = Double.valueOf("-6000");
+ assertEquals(-6000, aDoubleObj.doubleValue(), 0);
+ }
+
+ @Test
+ public void givenUsDecimalNumber_whenParsedWithNumberFormat_thenPass() throws ParseException {
+ Number parsedNumber = parseNumberWithLocale("4000.1", Locale.US);
+ assertEquals(4000.1, parsedNumber);
+ assertEquals(4000.1, parsedNumber.doubleValue(), 0);
+ assertEquals(4000, parsedNumber.intValue());
+ }
+
+ /**
+ * In most European countries (for example, France), comma is used as decimal in place of period.
+ * @throws ParseException if the input string contains special characters other than comma or decimal.
+ * In this test case, anything after decimal (period) is dropped when a European locale is set.
+ */
+ @Test
+ public void givenEuDecimalNumberHasComma_whenParsedWithNumberFormat_thenPass() throws ParseException {
+ Number parsedNumber = parseNumberWithLocale("4000,1", Locale.FRANCE);
+ LOG.info("Number parsed is: " + parsedNumber);
+ assertEquals(4000.1, parsedNumber);
+ assertEquals(4000.1, parsedNumber.doubleValue(), 0);
+ assertEquals(4000, parsedNumber.intValue());
+ }
+
+ /**
+ * Converts a string into a number retaining all decimals, and symbols valid in a locale.
+ * @param number the input string for a number.
+ * @param locale the locale to consider while parsing a number.
+ * @return the generic number object which can represent multiple number types.
+ * @throws ParseException when input contains invalid characters.
+ */
+ private Number parseNumberWithLocale(String number, Locale locale) throws ParseException {
+ locale = locale == null ? Locale.getDefault() : locale;
+ NumberFormat numberFormat = NumberFormat.getInstance(locale);
+ return numberFormat.parse(number);
+ }
+
+}
diff --git a/core-java-modules/core-java-io/README.md b/core-java-modules/core-java-io/README.md
index 9ce39459dd..6737ad6eb9 100644
--- a/core-java-modules/core-java-io/README.md
+++ b/core-java-modules/core-java-io/README.md
@@ -40,3 +40,4 @@
- [How to Write to a CSV File in Java](https://www.baeldung.com/java-csv)
- [List Files in a Directory in Java](https://www.baeldung.com/java-list-directory-files)
- [Java InputStream to Byte Array and ByteBuffer](https://www.baeldung.com/convert-input-stream-to-array-of-bytes)
+- [Introduction to the Java NIO Selector](https://www.baeldung.com/java-nio-selector)
diff --git a/core-java-modules/core-java-lang-oop-2/README.md b/core-java-modules/core-java-lang-oop-2/README.md
index af0aed5af3..2e36d251ca 100644
--- a/core-java-modules/core-java-lang-oop-2/README.md
+++ b/core-java-modules/core-java-lang-oop-2/README.md
@@ -4,3 +4,5 @@
### Relevant Articles:
- [Generic Constructors in Java](https://www.baeldung.com/java-generic-constructors)
+- [Cannot Reference “X” Before Supertype Constructor Has Been Called](https://www.baeldung.com/java-cannot-reference-x-before-supertype-constructor-error)
+- [Anonymous Classes in Java](https://www.baeldung.com/java-anonymous-classes)
diff --git a/core-java-modules/core-java-reflection/README.MD b/core-java-modules/core-java-reflection/README.MD
new file mode 100644
index 0000000000..c8766d6858
--- /dev/null
+++ b/core-java-modules/core-java-reflection/README.MD
@@ -0,0 +1,3 @@
+## Relevant Articles
+
+- [Void Type in Java](https://www.baeldung.com/java-void-type)
diff --git a/core-java-modules/core-java/README.md b/core-java-modules/core-java/README.md
index c2d1b4a06b..65fb5ddb9d 100644
--- a/core-java-modules/core-java/README.md
+++ b/core-java-modules/core-java/README.md
@@ -51,3 +51,4 @@
- [Java Bitwise Operators](https://www.baeldung.com/java-bitwise-operators)
- [Guide to Creating and Running a Jar File in Java](https://www.baeldung.com/java-create-jar)
- [Making a JSON POST Request With HttpURLConnection](https://www.baeldung.com/httpurlconnection-post)
+- [Convert Hex to ASCII in Java](https://www.baeldung.com/java-convert-hex-to-ascii)
diff --git a/core-java-modules/core-java/pom.xml b/core-java-modules/core-java/pom.xml
index b0f9fea26e..7942f3e7e2 100644
--- a/core-java-modules/core-java/pom.xml
+++ b/core-java-modules/core-java/pom.xml
@@ -454,7 +454,7 @@
2.8.2
- 3.5
+ 3.9
2.5
3.6.1
1.0.3
diff --git a/core-java/src/main/java/com/baeldung/exceptions/RootCauseFinder.java b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/RootCauseFinder.java
similarity index 90%
rename from core-java/src/main/java/com/baeldung/exceptions/RootCauseFinder.java
rename to core-java-modules/core-java/src/main/java/com/baeldung/exceptions/RootCauseFinder.java
index 064ae27ac1..cf449110e6 100644
--- a/core-java/src/main/java/com/baeldung/exceptions/RootCauseFinder.java
+++ b/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/RootCauseFinder.java
@@ -30,7 +30,7 @@ public class RootCauseFinder {
private AgeCalculator() {
}
- public static int calculateAge(String birthDate) throws CalculationException {
+ public static int calculateAge(String birthDate) {
if (birthDate == null || birthDate.isEmpty()) {
throw new IllegalArgumentException();
}
@@ -44,7 +44,7 @@ public class RootCauseFinder {
}
}
- private static LocalDate parseDate(String birthDateAsString) throws DateParseException {
+ private static LocalDate parseDate(String birthDateAsString) {
LocalDate birthDate;
try {
@@ -62,14 +62,14 @@ public class RootCauseFinder {
}
- static class CalculationException extends Exception {
+ static class CalculationException extends RuntimeException {
CalculationException(DateParseException ex) {
super(ex);
}
}
- static class DateParseException extends Exception {
+ static class DateParseException extends RuntimeException {
DateParseException(String input) {
super(input);
diff --git a/core-java/src/test/java/com/baeldung/exceptions/RootCauseFinderUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/exceptions/RootCauseFinderUnitTest.java
similarity index 100%
rename from core-java/src/test/java/com/baeldung/exceptions/RootCauseFinderUnitTest.java
rename to core-java-modules/core-java/src/test/java/com/baeldung/exceptions/RootCauseFinderUnitTest.java
diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml
index ed6a056448..2b563a7be4 100644
--- a/core-java-modules/pom.xml
+++ b/core-java-modules/pom.xml
@@ -15,6 +15,7 @@
pre-jpms
+ core-java-exceptions
diff --git a/core-java-modules/pre-jpms/README.MD b/core-java-modules/pre-jpms/README.MD
new file mode 100644
index 0000000000..8c9af82ba5
--- /dev/null
+++ b/core-java-modules/pre-jpms/README.MD
@@ -0,0 +1,3 @@
+## Relevant Articles
+
+- [Java 9 Migration Issues and Resolutions](https://www.baeldung.com/java-9-migration-issue)
diff --git a/core-java/pom.xml b/core-java/pom.xml
deleted file mode 100644
index 661e787149..0000000000
--- a/core-java/pom.xml
+++ /dev/null
@@ -1,492 +0,0 @@
-
- 4.0.0
- core-java
- 0.1.0-SNAPSHOT
- core-java
- jar
-
-
- com.baeldung
- parent-java
- 0.0.1-SNAPSHOT
- ../parent-java
-
-
-
-
-
- commons-io
- commons-io
- ${commons-io.version}
-
-
- org.apache.commons
- commons-lang3
- ${commons-lang3.version}
-
-
- org.unix4j
- unix4j-command
- ${unix4j.version}
-
-
- com.googlecode.grep4j
- grep4j
- ${grep4j.version}
-
-
-
-
- com.fasterxml.jackson.core
- jackson-databind
- ${jackson.version}
-
-
- com.google.code.gson
- gson
- ${gson.version}
-
-
-
- log4j
- log4j
- ${log4j.version}
-
-
- org.slf4j
- log4j-over-slf4j
- ${org.slf4j.version}
-
-
- org.projectlombok
- lombok
- ${lombok.version}
- provided
-
-
-
- org.assertj
- assertj-core
- ${assertj-core.version}
- test
-
-
- org.javamoney
- moneta
- ${javamoney.moneta.version}
-
-
- org.owasp.esapi
- esapi
- ${esapi.version}
-
-
- com.sun.messaging.mq
- fscontext
- ${fscontext.version}
-
-
- com.codepoetics
- protonpack
- ${protonpack.version}
-
-
- one.util
- streamex
- ${streamex.version}
-
-
- io.vavr
- vavr
- ${vavr.version}
-
-
- org.openjdk.jmh
- jmh-core
- ${jmh-core.version}
-
-
- org.openjdk.jmh
- jmh-generator-annprocess
- ${jmh-generator-annprocess.version}
-
-
- com.h2database
- h2
- ${h2database.version}
-
-
-
- org.javassist
- javassist
- ${javaassist.version}
-
-
- com.sun
- tools
- ${sun.tools.version}
- system
- ${java.home}/../lib/tools.jar
-
-
-
-
- core-java
-
-
- src/main/resources
- true
-
-
-
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
- prepare-package
-
- copy-dependencies
-
-
- ${project.build.directory}/libs
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
- ${maven-jar-plugin.version}
-
-
-
- true
- libs/
- org.baeldung.executable.ExecutableMavenJar
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-assembly-plugin
-
-
- package
-
- single
-
-
- ${project.basedir}
-
-
- org.baeldung.executable.ExecutableMavenJar
-
-
-
- jar-with-dependencies
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-shade-plugin
- ${maven-shade-plugin.version}
-
-
-
- shade
-
-
- true
-
-
- org.baeldung.executable.ExecutableMavenJar
-
-
-
-
-
-
-
-
- com.jolira
- onejar-maven-plugin
- ${onejar-maven-plugin.version}
-
-
-
- org.baeldung.executable.ExecutableMavenJar
- true
- ${project.build.finalName}-onejar.${project.packaging}
-
-
- one-jar
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
- ${spring-boot-maven-plugin.version}
-
-
-
- repackage
-
-
- spring-boot
- org.baeldung.executable.ExecutableMavenJar
-
-
-
-
-
-
- org.codehaus.mojo
- exec-maven-plugin
- ${exec-maven-plugin.version}
-
- java
- com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed
-
- -Xmx300m
- -XX:+UseParallelGC
- -classpath
-
- com.baeldung.outofmemoryerror.OutOfMemoryGCLimitExceed
-
-
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
- ${maven-javadoc-plugin.version}
-
-
- 1.8
-
-
-
-
-
-
-
- integration
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
- integration-test
-
- test
-
-
-
- **/*ManualTest.java
-
-
- **/*IntegrationTest.java
- **/*IntTest.java
-
-
-
-
-
-
- json
-
-
-
-
- org.codehaus.mojo
- exec-maven-plugin
- ${exec-maven-plugin.version}
-
-
- run-benchmarks
-
- none
-
- exec
-
-
- test
- java
-
- -classpath
-
- org.openjdk.jmh.Main
- .*
-
-
-
-
-
-
-
-
-
-
-
- buildAgentLoader
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
-
-
- package
-
- jar
-
-
- agentLoader
- target/classes
-
-
- true
-
- ${project.build.outputDirectory}/META-INF/MANIFEST.MF
-
-
-
- com/baeldung/instrumentation/application/AgentLoader.class
- com/baeldung/instrumentation/application/Launcher.class
-
-
-
-
-
-
-
-
-
- buildApplication
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
-
-
- package
-
- jar
-
-
- application
- target/classes
-
-
- true
-
- ${project.build.outputDirectory}/META-INF/MANIFEST.MF
-
-
-
- com/baeldung/instrumentation/application/MyAtm.class
- com/baeldung/instrumentation/application/MyAtmApplication.class
- com/baeldung/instrumentation/application/Launcher.class
-
-
-
-
-
-
-
-
-
- buildAgent
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
-
-
- package
-
- jar
-
-
- agent
- target/classes
-
-
- true
-
- ${project.build.outputDirectory}/META-INF/MANIFEST.MF
-
-
-
- com/baeldung/instrumentation/agent/AtmTransformer.class
- com/baeldung/instrumentation/agent/MyInstrumentationAgent.class
-
-
-
-
-
-
-
-
-
-
-
-
-
- 2.8.2
-
-
- 3.9
- 2.5
- 3.6.1
- 1.0.3
- 0.4
- 1.8.7
- 4.6-b01
- 1.13
- 0.6.5
- 0.9.0
-
-
- 3.10.0
-
-
- 2.21.0
-
- 1.1
- 1.4.197
- 2.1.0.1
- 1.19
-
- 1.19
- 3.0.0-M1
- 3.0.2
- 1.4.4
- 3.1.1
- 2.0.3.RELEASE
- 1.6.0
- 61.1
-
- 3.21.0-GA
-
- 1.8.0
-
-
diff --git a/core-kotlin-2/README.md b/core-kotlin-2/README.md
index 6d0b20135d..d75dd2208a 100644
--- a/core-kotlin-2/README.md
+++ b/core-kotlin-2/README.md
@@ -6,4 +6,5 @@
- [Kotlin Scope Functions](https://www.baeldung.com/kotlin-scope-functions)
- [Kotlin Annotations](https://www.baeldung.com/kotlin-annotations)
- [Split a List into Parts in Kotlin](https://www.baeldung.com/kotlin-split-list-into-parts)
-- [String Comparison in Kotlin](https://www.baeldung.com/kotlin-string-comparison)
\ No newline at end of file
+- [String Comparison in Kotlin](https://www.baeldung.com/kotlin-string-comparison)
+- [Guide to JVM Platform Annotations in Kotlin](https://www.baeldung.com/kotlin-jvm-annotations)
diff --git a/guava-collections-set/README.md b/guava-collections-set/README.md
new file mode 100644
index 0000000000..cfbe67c13e
--- /dev/null
+++ b/guava-collections-set/README.md
@@ -0,0 +1,4 @@
+
+### Relevant Articles:
+
+- [Guide to Guava Multiset](https://www.baeldung.com/guava-multiset)
diff --git a/jackson-2/README.md b/jackson-2/README.md
index 96ed960ac2..ee9f8458a0 100644
--- a/jackson-2/README.md
+++ b/jackson-2/README.md
@@ -7,4 +7,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
### Relevant Articles:
- [Mapping Multiple JSON Fields to a Single Java Field](https://www.baeldung.com/json-multiple-fields-single-java-field)
+- [How to Process YAML with Jackson](https://www.baeldung.com/jackson-yaml)
- [Working with Tree Model Nodes in Jackson](https://www.baeldung.com/jackson-json-node-tree-model)
+
diff --git a/java-collections-maps-2/README.md b/java-collections-maps-2/README.md
index 8bcafccfe8..ff84e93ce4 100644
--- a/java-collections-maps-2/README.md
+++ b/java-collections-maps-2/README.md
@@ -1,2 +1,3 @@
## Relevant Articles:
- [Map of Primitives in Java](https://www.baeldung.com/java-map-primitives)
+- [Copying a HashMap in Java](https://www.baeldung.com/java-copy-hashmap)
diff --git a/java-dates-2/README.md b/java-dates-2/README.md
index a6b5c8e574..35286115d4 100644
--- a/java-dates-2/README.md
+++ b/java-dates-2/README.md
@@ -1,2 +1,3 @@
## Relevant Articles:
- [Converting Between LocalDate and XMLGregorianCalendar](https://www.baeldung.com/java-localdate-to-xmlgregoriancalendar)
+- [Convert Time to Milliseconds in Java](https://www.baeldung.com/java-time-milliseconds)
diff --git a/java-strings-2/README.MD b/java-strings-2/README.MD
new file mode 100644
index 0000000000..edda92221d
--- /dev/null
+++ b/java-strings-2/README.MD
@@ -0,0 +1,4 @@
+## Relevant Articles
+
+- [Java Localization – Formatting Messages](https://www.baeldung.com/java-localization-messages-formatting)
+- [Check If a String Contains a Substring](https://www.baeldung.com/java-string-contains-substring)
diff --git a/jee-7/src/main/java/com/baeldung/singleton/Car.java b/jee-7/src/main/java/com/baeldung/singleton/Car.java
new file mode 100644
index 0000000000..0cf7281294
--- /dev/null
+++ b/jee-7/src/main/java/com/baeldung/singleton/Car.java
@@ -0,0 +1,28 @@
+package com.baeldung.singleton;
+
+public class Car {
+
+ private String type;
+ private String model;
+ private boolean serviced = false;
+
+ public Car(String type, String model) {
+ super();
+ this.type = type;
+ this.model = model;
+ }
+
+ public boolean isServiced () {
+ return serviced;
+ }
+
+ public void setServiced(Boolean serviced) {
+ this.serviced = serviced;
+ }
+
+ @Override
+ public String toString() {
+ return "Car [type=" + type + ", model=" + model + "]";
+ }
+
+}
diff --git a/jee-7/src/main/java/com/baeldung/singleton/CarServiceBean.java b/jee-7/src/main/java/com/baeldung/singleton/CarServiceBean.java
new file mode 100644
index 0000000000..b824882d5d
--- /dev/null
+++ b/jee-7/src/main/java/com/baeldung/singleton/CarServiceBean.java
@@ -0,0 +1,23 @@
+package com.baeldung.singleton;
+
+import java.util.UUID;
+
+import javax.enterprise.context.Dependent;
+
+import org.springframework.web.context.annotation.RequestScope;
+
+@RequestScope
+public class CarServiceBean {
+
+ private UUID id = UUID.randomUUID();
+
+ public UUID getId() {
+ return this.id;
+ }
+
+ @Override
+ public String toString() {
+ return "CarService [id=" + id + "]";
+ }
+
+}
diff --git a/jee-7/src/main/java/com/baeldung/singleton/CarServiceEjbSingleton.java b/jee-7/src/main/java/com/baeldung/singleton/CarServiceEjbSingleton.java
new file mode 100644
index 0000000000..1bbffdd61e
--- /dev/null
+++ b/jee-7/src/main/java/com/baeldung/singleton/CarServiceEjbSingleton.java
@@ -0,0 +1,46 @@
+package com.baeldung.singleton;
+
+import java.util.UUID;
+
+import javax.ejb.Singleton;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class CarServiceEjbSingleton {
+
+ private static Logger LOG = LoggerFactory.getLogger(CarServiceEjbSingleton.class);
+
+ private UUID id = UUID.randomUUID();
+
+ private static int serviceQueue;
+
+ public UUID getId() {
+ return this.id;
+ }
+
+ @Override
+ public String toString() {
+ return "CarServiceEjbSingleton [id=" + id + "]";
+ }
+
+ public int service(Car car) {
+ serviceQueue++;
+ LOG.info("Car {} is being serviced @ CarServiceEjbSingleton - serviceQueue: {}", car, serviceQueue);
+ simulateService(car);
+ serviceQueue--;
+ LOG.info("Car service for {} is completed - serviceQueue: {}", car, serviceQueue);
+ return serviceQueue;
+ }
+
+ private void simulateService(Car car) {
+ try {
+ Thread.sleep(100);
+ car.setServiced(true);
+ } catch (InterruptedException e) {
+ LOG.error("CarServiceEjbSingleton::InterruptedException: {}", e);
+ }
+ }
+
+}
diff --git a/jee-7/src/main/java/com/baeldung/singleton/CarServiceSingleton.java b/jee-7/src/main/java/com/baeldung/singleton/CarServiceSingleton.java
new file mode 100644
index 0000000000..223d139346
--- /dev/null
+++ b/jee-7/src/main/java/com/baeldung/singleton/CarServiceSingleton.java
@@ -0,0 +1,47 @@
+package com.baeldung.singleton;
+
+import java.util.UUID;
+
+import javax.inject.Singleton;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class CarServiceSingleton {
+
+ private static Logger LOG = LoggerFactory.getLogger(CarServiceSingleton.class);
+
+ private UUID id = UUID.randomUUID();
+
+ private static int serviceQueue;
+
+ public UUID getId() {
+ return this.id;
+ }
+
+ @Override
+ public String toString() {
+ return "CarServiceSingleton [id=" + id + "]";
+ }
+
+ public int service(Car car) {
+ serviceQueue++;
+ LOG.info("Car {} is being serviced @ CarServiceSingleton - serviceQueue: {}", car, serviceQueue);
+ simulateService(car);
+ serviceQueue--;
+ LOG.info("Car service for {} is completed - serviceQueue: {}", car, serviceQueue);
+ return serviceQueue;
+
+ }
+
+ private void simulateService(Car car) {
+ try {
+ Thread.sleep(100);
+ car.setServiced(true);
+ } catch (InterruptedException e) {
+ LOG.error("CarServiceSingleton::InterruptedException: {}", e);
+ }
+ }
+
+}
diff --git a/jee-7/src/test/java/com/baeldung/singleton/CarServiceIntegrationTest.java b/jee-7/src/test/java/com/baeldung/singleton/CarServiceIntegrationTest.java
new file mode 100644
index 0000000000..b828296dca
--- /dev/null
+++ b/jee-7/src/test/java/com/baeldung/singleton/CarServiceIntegrationTest.java
@@ -0,0 +1,142 @@
+package com.baeldung.singleton;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.ejb.EJB;
+import javax.inject.Inject;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.Before;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@RunWith(Arquillian.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class CarServiceIntegrationTest {
+
+ public static final Logger LOG = LoggerFactory.getLogger(CarServiceIntegrationTest.class);
+
+ @Deployment
+ public static JavaArchive createDeployment() {
+ return ShrinkWrap.create(JavaArchive.class)
+ .addClasses(CarServiceBean.class, CarServiceSingleton.class, CarServiceEjbSingleton.class, Car.class)
+ .addAsResource("META-INF/persistence.xml")
+ .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+ }
+
+ @Inject
+ private CarServiceBean carServiceBean;
+
+ @Inject
+ private CarServiceSingleton carServiceSingleton;
+
+ @EJB
+ private CarServiceEjbSingleton carServiceEjbSingleton;
+
+ private static Map idMap = new HashMap<>();
+
+ @Before
+ public void setUp() {
+ // populate idMap only on first run
+ if (idMap.isEmpty()) {
+ LOG.info("setUp::carServiceBean: {}", carServiceBean.getId());
+ idMap.put("carServiceBeanId", carServiceBean.getId());
+
+ LOG.info("setUp::carServiceSingleton: {}", carServiceSingleton.getId());
+ idMap.put("carServiceSingletonId", carServiceSingleton.getId());
+
+ LOG.info("setUp::carServiceEjbSingleton: {}", carServiceEjbSingleton.getId());
+ idMap.put("carServiceEjbSingletonId", carServiceEjbSingleton.getId());
+ }
+ }
+
+ @Test
+ public void givenRun1_whenGetId_thenSingletonIdEqual() {
+ int testRun = 1;
+
+ assertNotNull(carServiceBean);
+ assertNotNull(carServiceSingleton);
+ assertNotNull(carServiceEjbSingleton);
+
+ UUID carServiceBeanId = carServiceBean.getId();
+ assertEquals(idMap.get("carServiceBeanId"), carServiceBeanId);
+ LOG.info("Test run {}::carServiceBeanId: {}", testRun, carServiceBeanId);
+
+ UUID carServiceSingletonId = carServiceSingleton.getId();
+ assertEquals(idMap.get("carServiceSingletonId"), carServiceSingletonId);
+ LOG.info("Test run {}::carServiceSingletonId: {}", testRun, carServiceSingletonId);
+
+ UUID carServiceEjbSingletonId = carServiceEjbSingleton.getId();
+ assertEquals(idMap.get("carServiceEjbSingletonId"), carServiceEjbSingletonId);
+ LOG.info("Test run {}::carServiceEjbSingletonId: {}", testRun, carServiceEjbSingletonId);
+ }
+
+ @Test
+ public void givenRun2_whenGetId_thenSingletonIdEqual() {
+ int testRun = 2;
+
+ assertNotNull(carServiceBean);
+ assertNotNull(carServiceSingleton);
+ assertNotNull(carServiceEjbSingleton);
+
+ UUID carServiceBeanId = carServiceBean.getId();
+ assertNotEquals(idMap.get("carServiceBeanId"), carServiceBeanId);
+ LOG.info("Test run {}::carServiceBeanId: {}", testRun, carServiceBeanId);
+
+ UUID carServiceSingletonId = carServiceSingleton.getId();
+ assertEquals(idMap.get("carServiceSingletonId"), carServiceSingletonId);
+ LOG.info("Test run {}::carServiceSingletonId: {}", testRun, carServiceSingletonId);
+
+ UUID carServiceEjbSingletonId = carServiceEjbSingleton.getId();
+ assertEquals(idMap.get("carServiceEjbSingletonId"), carServiceEjbSingletonId);
+ LOG.info("Test run {}::carServiceEjbSingletonId: {}", testRun, carServiceEjbSingletonId);
+ }
+
+ @Test
+ public void givenRun3_whenSingleton_thenNoLocking() {
+ for (int i = 0; i < 10; i++) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ String model = Double.toString(Math.round(Math.random() * 100));
+ Car car = new Car("Speedster", model);
+ int serviceQueue = carServiceSingleton.service(car);
+ assertTrue(serviceQueue < 10);
+ }
+ }).start();
+ }
+ return;
+ }
+
+ @Test
+ public void givenRun4_whenEjb_thenLocking() {
+ for (int i = 0; i < 10; i++) {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ String model = Double.toString(Math.round(Math.random() * 100));
+ Car car = new Car("Speedster", model);
+ int serviceQueue = carServiceEjbSingleton.service(car);
+ assertEquals(0, serviceQueue);
+ }
+ }).start();
+ }
+ return;
+ }
+
+}
\ No newline at end of file
diff --git a/jhipster-5/README.md b/jhipster-5/README.md
new file mode 100644
index 0000000000..0537f5b1a5
--- /dev/null
+++ b/jhipster-5/README.md
@@ -0,0 +1,3 @@
+## Relevant articles:
+
+- [Creating New APIs and Views in JHipster](https://www.baeldung.com/jhipster-new-apis-and-views)
diff --git a/kotlin-libraries/build.gradle b/kotlin-libraries/build.gradle
index b244df34b0..afb92de49e 100644
--- a/kotlin-libraries/build.gradle
+++ b/kotlin-libraries/build.gradle
@@ -7,6 +7,7 @@ version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.2.41'
ext.ktor_version = '0.9.2'
+ ext.khttp_version = '0.1.0'
repositories {
mavenCentral()
@@ -47,11 +48,16 @@ dependencies {
compile "io.ktor:ktor-server-netty:$ktor_version"
compile "ch.qos.logback:logback-classic:1.2.1"
compile "io.ktor:ktor-gson:$ktor_version"
+ compile "khttp:khttp:$khttp_version"
testCompile group: 'junit', name: 'junit', version: '4.12'
+ testCompile group: 'org.jetbrains.spek', name: 'spek-api', version: '1.1.5'
+ testCompile group: 'org.jetbrains.spek', name: 'spek-subject-extension', version: '1.1.5'
+ testCompile group: 'org.jetbrains.spek', name: 'spek-junit-platform-engine', version: '1.1.5'
implementation 'com.beust:klaxon:3.0.1'
+ implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
}
task runServer(type: JavaExec) {
main = 'APIServer'
classpath = sourceSets.main.runtimeClasspath
-}
\ No newline at end of file
+}
diff --git a/kotlin-libraries/pom.xml b/kotlin-libraries/pom.xml
index 3d2c7337b0..b75c77f358 100644
--- a/kotlin-libraries/pom.xml
+++ b/kotlin-libraries/pom.xml
@@ -166,6 +166,12 @@
2.6
compile
+
+
+ io.reactivex.rxjava2
+ rxkotlin
+ 2.3.0
+
diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt
new file mode 100644
index 0000000000..979ed3f809
--- /dev/null
+++ b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt
@@ -0,0 +1,157 @@
+package com.baeldung.kotlin.rxkotlin
+
+import io.reactivex.Maybe
+import io.reactivex.Observable
+import io.reactivex.functions.BiFunction
+import io.reactivex.rxkotlin.*
+import io.reactivex.subjects.PublishSubject
+import org.junit.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertFalse
+
+class RxKotlinTest {
+
+ @Test
+ fun whenBooleanArrayToObserver_thenBooleanObserver() {
+ val observable = listOf(true, false, false).toObservable()
+ observable.test().assertValues(true, false, false)
+ }
+
+ @Test
+ fun whenBooleanArrayToFlowable_thenBooleanFlowable() {
+ val flowable = listOf(true, false, false).toFlowable()
+ flowable.buffer(2).test().assertValues(listOf(true, false), listOf(false))
+ }
+
+ @Test
+ fun whenIntArrayToObserver_thenIntObserver() {
+ val observable = listOf(1, 1, 2, 3).toObservable()
+ observable.test().assertValues(1, 1, 2, 3)
+ }
+
+ @Test
+ fun whenIntArrayToFlowable_thenIntFlowable() {
+ val flowable = listOf(1, 1, 2, 3).toFlowable()
+ flowable.buffer(2).test().assertValues(listOf(1, 1), listOf(2, 3))
+ }
+
+ @Test
+ fun whenObservablePairToMap_thenSingleNoDuplicates() {
+ val list = listOf(Pair("a", 1), Pair("b", 2), Pair("c", 3), Pair("a", 4))
+ val observable = list.toObservable()
+ val map = observable.toMap()
+ assertEquals(mapOf(Pair("a", 4), Pair("b", 2), Pair("c", 3)), map.blockingGet())
+ }
+
+ @Test
+ fun whenObservablePairToMap_thenSingleWithDuplicates() {
+ val list = listOf(Pair("a", 1), Pair("b", 2), Pair("c", 3), Pair("a", 4))
+ val observable = list.toObservable()
+ val map = observable.toMultimap()
+ assertEquals(
+ mapOf(Pair("a", listOf(1, 4)), Pair("b", listOf(2)), Pair("c", listOf(3))),
+ map.blockingGet())
+ }
+
+ @Test
+ fun whenMergeAll_thenStream() {
+ val subject = PublishSubject.create>()
+ val observable = subject.mergeAll()
+ val testObserver = observable.test()
+ subject.onNext(Observable.just("first", "second"))
+ testObserver.assertValues("first", "second")
+ subject.onNext(Observable.just("third", "fourth"))
+ subject.onNext(Observable.just("fifth"))
+ testObserver.assertValues("first", "second", "third", "fourth", "fifth")
+ }
+
+ @Test
+ fun whenConcatAll_thenStream() {
+ val subject = PublishSubject.create>()
+ val observable = subject.concatAll()
+ val testObserver = observable.test()
+ subject.onNext(Observable.just("first", "second"))
+ testObserver.assertValues("first", "second")
+ subject.onNext(Observable.just("third", "fourth"))
+ subject.onNext(Observable.just("fifth"))
+ testObserver.assertValues("first", "second", "third", "fourth", "fifth")
+ }
+
+ @Test
+ fun whenSwitchLatest_thenStream() {
+ val subject = PublishSubject.create>()
+ val observable = subject.switchLatest()
+ val testObserver = observable.test()
+ subject.onNext(Observable.just("first", "second"))
+ testObserver.assertValues("first", "second")
+ subject.onNext(Observable.just("third", "fourth"))
+ subject.onNext(Observable.just("fifth"))
+ testObserver.assertValues("first", "second", "third", "fourth", "fifth")
+ }
+
+ @Test
+ fun whenMergeAllMaybes_thenObservable() {
+ val subject = PublishSubject.create>()
+ val observable = subject.mergeAllMaybes()
+ val testObserver = observable.test()
+ subject.onNext(Maybe.just(1))
+ subject.onNext(Maybe.just(2))
+ subject.onNext(Maybe.empty())
+ testObserver.assertValues(1, 2)
+ subject.onNext(Maybe.error(Exception("")))
+ subject.onNext(Maybe.just(3))
+ testObserver.assertValues(1, 2).assertError(Exception::class.java)
+ }
+
+ @Test
+ fun whenMerge_thenStream() {
+ val observables = mutableListOf(Observable.just("first", "second"))
+ val observable = observables.merge()
+ observables.add(Observable.just("third", "fourth"))
+ observables.add(Observable.error(Exception("e")))
+ observables.add(Observable.just("fifth"))
+
+ observable.test().assertValues("first", "second", "third", "fourth").assertError(Exception::class.java)
+ }
+
+ @Test
+ fun whenMergeDelayError_thenStream() {
+ val observables = mutableListOf>(Observable.error(Exception("e1")))
+ val observable = observables.mergeDelayError()
+ observables.add(Observable.just("1", "2"))
+ observables.add(Observable.error(Exception("e2")))
+ observables.add(Observable.just("3"))
+
+ observable.test().assertValues("1", "2", "3").assertError(Exception::class.java)
+ }
+
+ @Test
+ fun whenCast_thenUniformType() {
+ val observable = Observable.just(1, 1, 2, 3)
+ observable.cast().test().assertValues(1, 1, 2, 3)
+ }
+
+ @Test
+ fun whenOfType_thenFilter() {
+ val observable = Observable.just(1, "and", 2, "and")
+ observable.ofType().test().assertValues(1, 2)
+ }
+
+ @Test
+ fun whenFunction_thenCompletable() {
+ var value = 0
+ val completable = { value = 3 }.toCompletable()
+ assertFalse(completable.test().isCancelled)
+ assertEquals(3, value)
+ }
+
+ @Test
+ fun whenHelper_thenMoreIdiomaticKotlin() {
+ val zipWith = Observable.just(1).zipWith(Observable.just(2)) { a, b -> a + b }
+ zipWith.subscribeBy(onNext = { println(it) })
+ val zip = Observables.zip(Observable.just(1), Observable.just(2)) { a, b -> a + b }
+ zip.subscribeBy(onNext = { println(it) })
+ val zipOrig = Observable.zip(Observable.just(1), Observable.just(2), BiFunction { a, b -> a + b })
+ zipOrig.subscribeBy(onNext = { println(it) })
+ }
+}
diff --git a/libraries-2/README.md b/libraries-2/README.md
index 3d5dba80ee..8243b9f82c 100644
--- a/libraries-2/README.md
+++ b/libraries-2/README.md
@@ -1,3 +1,7 @@
-## Relevant Articles
+### Relevant Articles:
+
+- [A Guide to jBPM with Java](https://www.baeldung.com/jbpm-java)
- [Guide to Classgraph Library](https://www.baeldung.com/classgraph)
+- [Create a Java Command Line Program with Picocli](https://www.baeldung.com/java-picocli-create-command-line-program)
+
diff --git a/logging-modules/logback/README.md b/logging-modules/logback/README.md
index df55492b69..58dc8ce541 100644
--- a/logging-modules/logback/README.md
+++ b/logging-modules/logback/README.md
@@ -1,3 +1,4 @@
### Relevant Articles:
- [Get Log Output in JSON](https://www.baeldung.com/java-log-json-output)
+- [SLF4J Warning: Class Path Contains Multiple SLF4J Bindings](https://www.baeldung.com/slf4j-classpath-multiple-bindings)
diff --git a/persistence-modules/README.md b/persistence-modules/README.md
index 2fbaf25f2f..e9a7d625cc 100644
--- a/persistence-modules/README.md
+++ b/persistence-modules/README.md
@@ -5,7 +5,6 @@
### Relevant Articles:
- [Introduction to Hibernate Search](http://www.baeldung.com/hibernate-search)
-- [Bootstrapping Hibernate 5 with Spring](http://www.baeldung.com/hibernate-5-spring)
- [Introduction to Lettuce – the Java Redis Client](http://www.baeldung.com/java-redis-lettuce)
- [A Guide to Jdbi](http://www.baeldung.com/jdbi)
- [Pessimistic Locking in JPA](http://www.baeldung.com/jpa-pessimistic-locking)
@@ -13,3 +12,6 @@
- [Spring Data with Reactive Cassandra](https://www.baeldung.com/spring-data-cassandra-reactive)
- [Spring Data JPA – Derived Delete Methods](https://www.baeldung.com/spring-data-jpa-deleteby)
- [Difference Between save() and saveAndFlush() in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-save-saveandflush)
+- [Spring Boot with Hibernate](https://www.baeldung.com/spring-boot-hibernate)
+- [Persisting Maps with Hibernate](https://www.baeldung.com/hibernate-persisting-maps)
+- [Difference Between @Size, @Length, and @Column(length=value)](https://www.baeldung.com/jpa-size-length-column-differences)
diff --git a/persistence-modules/core-java-persistence/README.md b/persistence-modules/core-java-persistence/README.md
index 26bd4bf00f..1187cc15c4 100644
--- a/persistence-modules/core-java-persistence/README.md
+++ b/persistence-modules/core-java-persistence/README.md
@@ -8,3 +8,4 @@
- [Introduction to the JDBC RowSet Interface in Java](http://www.baeldung.com/java-jdbc-rowset)
- [A Simple Guide to Connection Pooling in Java](https://www.baeldung.com/java-connection-pooling)
- [Guide to the JDBC ResultSet Interface](https://www.baeldung.com/jdbc-resultset)
+- [Types of SQL Joins](https://www.baeldung.com/sql-joins)
diff --git a/persistence-modules/hibernate-mapping/README.md b/persistence-modules/hibernate-mapping/README.md
new file mode 100644
index 0000000000..223d93e1ed
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/README.md
@@ -0,0 +1,4 @@
+
+### Relevant Articles:
+
+- [Persisting Maps with Hibernate](https://www.baeldung.com/hibernate-persisting-maps)
diff --git a/persistence-modules/java-jpa/README.md b/persistence-modules/java-jpa/README.md
index 5be1015942..34d03b3259 100644
--- a/persistence-modules/java-jpa/README.md
+++ b/persistence-modules/java-jpa/README.md
@@ -2,8 +2,9 @@
- [A Guide to SqlResultSetMapping](http://www.baeldung.com/jpa-sql-resultset-mapping)
- [A Guide to Stored Procedures with JPA](http://www.baeldung.com/jpa-stored-procedures)
-- [Fixing the JPA error “java.lang.String cannot be cast to [Ljava.lang.String;”]](https://www.baeldung.com/jpa-error-java-lang-string-cannot-be-cast)
+- [Fixing the JPA error “java.lang.String cannot be cast to Ljava.lang.String;”](https://www.baeldung.com/jpa-error-java-lang-string-cannot-be-cast)
- [JPA Entity Graph](https://www.baeldung.com/jpa-entity-graph)
- [JPA 2.2 Support for Java 8 Date/Time Types](https://www.baeldung.com/jpa-java-time)
- [Converting Between LocalDate and SQL Date](https://www.baeldung.com/java-convert-localdate-sql-date)
- [Combining JPA And/Or Criteria Predicates](https://www.baeldung.com/jpa-and-or-criteria-predicates)
+- [Types of JPA Queries](https://www.baeldung.com/jpa-queries)
diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/basicannotation/Course.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/basicannotation/Course.java
new file mode 100644
index 0000000000..cc5a83420c
--- /dev/null
+++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/basicannotation/Course.java
@@ -0,0 +1,33 @@
+package com.baeldung.jpa.basicannotation;
+
+import javax.persistence.Basic;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+
+@Entity
+public class Course {
+
+ @Id
+ private int id;
+
+ @Basic(optional = false, fetch = FetchType.LAZY)
+ private String name;
+
+ 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;
+ }
+}
+
diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Article.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Article.java
new file mode 100644
index 0000000000..d534f44e14
--- /dev/null
+++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Article.java
@@ -0,0 +1,91 @@
+package com.baeldung.jpa.enums;
+
+import javax.persistence.*;
+
+@Entity
+public class Article {
+
+ @Id
+ private int id;
+
+ private String title;
+
+ @Enumerated(EnumType.ORDINAL)
+ private Status status;
+
+ @Enumerated(EnumType.STRING)
+ private Type type;
+
+ @Basic
+ private int priorityValue;
+
+ @Transient
+ private Priority priority;
+
+ private Category category;
+
+ public Article() {
+ }
+
+ @PostLoad
+ void fillTransient() {
+ if (priorityValue > 0) {
+ this.priority = Priority.of(priorityValue);
+ }
+ }
+
+ @PrePersist
+ void fillPersistent() {
+ if (priority != null) {
+ this.priorityValue = priority.getPriority();
+ }
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+ public void setStatus(Status status) {
+ this.status = status;
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public void setType(Type type) {
+ this.type = type;
+ }
+
+ public Priority getPriority() {
+ return priority;
+ }
+
+ public void setPriority(Priority priority) {
+ this.priority = priority;
+ }
+
+ public Category getCategory() {
+ return category;
+ }
+
+ public void setCategory(Category category) {
+ this.category = category;
+ }
+}
diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Category.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Category.java
new file mode 100644
index 0000000000..83b81da01e
--- /dev/null
+++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Category.java
@@ -0,0 +1,17 @@
+package com.baeldung.jpa.enums;
+
+import java.util.stream.Stream;
+
+public enum Category {
+ SPORT("S"), MUSIC("M"), TECHNOLOGY("T");
+
+ private String code;
+
+ Category(String code) {
+ this.code = code;
+ }
+
+ public String getCode() {
+ return code;
+ }
+}
diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/CategoryConverter.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/CategoryConverter.java
new file mode 100644
index 0000000000..98960f1569
--- /dev/null
+++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/CategoryConverter.java
@@ -0,0 +1,28 @@
+package com.baeldung.jpa.enums;
+
+import javax.persistence.AttributeConverter;
+import javax.persistence.Converter;
+import java.util.stream.Stream;
+
+@Converter(autoApply = true)
+public class CategoryConverter implements AttributeConverter {
+ @Override
+ public String convertToDatabaseColumn(Category category) {
+ if (category == null) {
+ return null;
+ }
+ return category.getCode();
+ }
+
+ @Override
+ public Category convertToEntityAttribute(final String code) {
+ if (code == null) {
+ return null;
+ }
+
+ return Stream.of(Category.values())
+ .filter(c -> c.getCode().equals(code))
+ .findFirst()
+ .orElseThrow(IllegalArgumentException::new);
+ }
+}
diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Priority.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Priority.java
new file mode 100644
index 0000000000..42ee254303
--- /dev/null
+++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Priority.java
@@ -0,0 +1,24 @@
+package com.baeldung.jpa.enums;
+
+import java.util.stream.Stream;
+
+public enum Priority {
+ LOW(100), MEDIUM(200), HIGH(300);
+
+ private int priority;
+
+ private Priority(int priority) {
+ this.priority = priority;
+ }
+
+ public int getPriority() {
+ return priority;
+ }
+
+ public static Priority of(int priority) {
+ return Stream.of(Priority.values())
+ .filter(p -> p.getPriority() == priority)
+ .findFirst()
+ .orElseThrow(IllegalArgumentException::new);
+ }
+}
diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Status.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Status.java
new file mode 100644
index 0000000000..80d5662c7a
--- /dev/null
+++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Status.java
@@ -0,0 +1,5 @@
+package com.baeldung.jpa.enums;
+
+public enum Status {
+ OPEN, REVIEW, APPROVED, REJECTED;
+}
diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Type.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Type.java
new file mode 100644
index 0000000000..80459fbd3c
--- /dev/null
+++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/enums/Type.java
@@ -0,0 +1,5 @@
+package com.baeldung.jpa.enums;
+
+enum Type {
+ INTERNAL, EXTERNAL;
+}
diff --git a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml
index 21a757f490..52cc1e01d9 100644
--- a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml
+++ b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml
@@ -26,6 +26,8 @@
org.hibernate.jpa.HibernatePersistenceProvider
com.baeldung.jpa.stringcast.Message
+ com.baeldung.jpa.enums.Article
+ com.baeldung.jpa.enums.CategoryConverter
true
@@ -146,4 +148,4 @@
-
+
\ No newline at end of file
diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/basicannotation/BasicAnnotationIntegrationTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/basicannotation/BasicAnnotationIntegrationTest.java
new file mode 100644
index 0000000000..8580aa6602
--- /dev/null
+++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/basicannotation/BasicAnnotationIntegrationTest.java
@@ -0,0 +1,56 @@
+package com.baeldung.jpa.basicannotation;
+
+import org.hibernate.PropertyValueException;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class BasicAnnotationIntegrationTest {
+
+ private static EntityManager entityManager;
+ private static EntityManagerFactory entityManagerFactory;
+
+ @BeforeClass
+ public void setup() {
+ entityManagerFactory = Persistence.createEntityManagerFactory("java-jpa-scheduled-day");
+ entityManager = entityManagerFactory.createEntityManager();
+ }
+
+ @Test
+ public void givenACourse_whenCourseNamePresent_shouldPersist() {
+ Course course = new Course();
+ course.setName("Computers");
+
+ entityManager.persist(course);
+ entityManager.flush();
+ entityManager.clear();
+
+ }
+
+ @Test(expected = PropertyValueException.class)
+ public void givenACourse_whenCourseNameAbsent_shouldFail() {
+ Course course = new Course();
+
+ entityManager.persist(course);
+ entityManager.flush();
+ entityManager.clear();
+ }
+
+ @AfterClass
+ public void destroy() {
+
+ if (entityManager != null) {
+ entityManager.close();
+ }
+ if (entityManagerFactory != null) {
+ entityManagerFactory.close();
+ }
+ }
+}
diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/enums/ArticleUnitTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/enums/ArticleUnitTest.java
new file mode 100644
index 0000000000..82f3abc04d
--- /dev/null
+++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/enums/ArticleUnitTest.java
@@ -0,0 +1,118 @@
+package com.baeldung.jpa.enums;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+import javax.persistence.Persistence;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class ArticleUnitTest {
+
+ private static EntityManager em;
+ private static EntityManagerFactory emFactory;
+
+ @BeforeClass
+ public static void setup() {
+ Map properties = new HashMap();
+ properties.put("hibernate.show_sql", "true");
+ properties.put("hibernate.format_sql", "true");
+ emFactory = Persistence.createEntityManagerFactory("jpa-h2", properties);
+ em = emFactory.createEntityManager();
+ }
+
+ @Test
+ public void shouldPersistStatusEnumOrdinalValue() {
+ // given
+ Article article = new Article();
+ article.setId(1);
+ article.setTitle("ordinal title");
+ article.setStatus(Status.OPEN);
+
+ // when
+ EntityTransaction tx = em.getTransaction();
+ tx.begin();
+ em.persist(article);
+ tx.commit();
+
+ // then
+ Article persistedArticle = em.find(Article.class, 1);
+
+ assertEquals(1, persistedArticle.getId());
+ assertEquals("ordinal title", persistedArticle.getTitle());
+ assertEquals(Status.OPEN, persistedArticle.getStatus());
+ }
+
+ @Test
+ public void shouldPersistTypeEnumStringValue() {
+ // given
+ Article article = new Article();
+ article.setId(2);
+ article.setTitle("string title");
+ article.setType(Type.EXTERNAL);
+
+ // when
+ EntityTransaction tx = em.getTransaction();
+ tx.begin();
+ em.persist(article);
+ tx.commit();
+
+ // then
+ Article persistedArticle = em.find(Article.class, 2);
+
+ assertEquals(2, persistedArticle.getId());
+ assertEquals("string title", persistedArticle.getTitle());
+ assertEquals(Type.EXTERNAL, persistedArticle.getType());
+ }
+
+ @Test
+ public void shouldPersistPriorityIntValue() {
+ // given
+ Article article = new Article();
+ article.setId(3);
+ article.setTitle("callback title");
+ article.setPriority(Priority.HIGH);
+
+ // when
+ EntityTransaction tx = em.getTransaction();
+ tx.begin();
+ em.persist(article);
+ tx.commit();
+
+ // then
+ Article persistedArticle = em.find(Article.class, 3);
+
+ assertEquals(3, persistedArticle.getId());
+ assertEquals("callback title", persistedArticle.getTitle());
+ assertEquals(Priority.HIGH, persistedArticle.getPriority());
+
+ }
+
+ @Test
+ public void shouldPersistCategoryEnumConvertedValue() {
+ // given
+ Article article = new Article();
+ article.setId(4);
+ article.setTitle("converted title");
+ article.setCategory(Category.MUSIC);
+
+ // when
+ EntityTransaction tx = em.getTransaction();
+ tx.begin();
+ em.persist(article);
+ tx.commit();
+
+ // then
+ Article persistedArticle = em.find(Article.class, 4);
+
+ assertEquals(4, persistedArticle.getId());
+ assertEquals("converted title", persistedArticle.getTitle());
+ assertEquals(Category.MUSIC, persistedArticle.getCategory());
+ }
+
+}
\ No newline at end of file
diff --git a/persistence-modules/java-mongodb/README.md b/persistence-modules/java-mongodb/README.md
index ded2b220f1..6d31467db3 100644
--- a/persistence-modules/java-mongodb/README.md
+++ b/persistence-modules/java-mongodb/README.md
@@ -2,3 +2,4 @@
- [A Guide to MongoDB with Java](http://www.baeldung.com/java-mongodb)
- [A Simple Tagging Implementation with MongoDB](http://www.baeldung.com/mongodb-tagging)
+- [MongoDB BSON Guide](https://www.baeldung.com/mongodb-bson)
diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml
index 67a5c36fed..ba3baf6636 100644
--- a/persistence-modules/pom.xml
+++ b/persistence-modules/pom.xml
@@ -55,5 +55,6 @@
spring-hibernate-5
spring-hibernate4
spring-jpa
+ spring-persistence-simple
diff --git a/persistence-modules/spring-data-jpa-2/README.md b/persistence-modules/spring-data-jpa-2/README.md
index 41381ab82a..393d15d6f1 100644
--- a/persistence-modules/spring-data-jpa-2/README.md
+++ b/persistence-modules/spring-data-jpa-2/README.md
@@ -1,6 +1,14 @@
-=========
-
-## Spring Data JPA Example Project
-
-### Relevant Articles:
-- [Spring Data JPA – Derived Delete Methods](https://www.baeldung.com/spring-data-jpa-deleteby)
+=========
+
+## Spring Data JPA Example Project
+
+### Relevant Articles:
+- [Spring Data JPA – Derived Delete Methods](https://www.baeldung.com/spring-data-jpa-deleteby)
+- [JPA Join Types](https://www.baeldung.com/jpa-join-types)
+- [Case Insensitive Queries with Spring Data Repository](https://www.baeldung.com/spring-data-case-insensitive-queries)
+- [The Exists Query in Spring Data](https://www.baeldung.com/spring-data-exists-query)
+- [Spring Data JPA Repository Populators](https://www.baeldung.com/spring-data-jpa-repository-populators)
+- [Spring Data JPA and Null Parameters](https://www.baeldung.com/spring-data-jpa-null-parameters)
+- [Spring Data JPA Projections](https://www.baeldung.com/spring-data-jpa-projections)
+- [JPA @Embedded And @Embeddable](https://www.baeldung.com/jpa-embedded-embeddable)
+- [Spring Data JPA Delete and Relationships](https://www.baeldung.com/spring-data-jpa-delete)
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/entity/User.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/entity/User.java
new file mode 100644
index 0000000000..e6d38f775b
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/entity/User.java
@@ -0,0 +1,70 @@
+package com.baeldung.derivedquery.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.time.ZonedDateTime;
+
+@Table(name = "users")
+@Entity
+public class User {
+
+ @Id
+ @GeneratedValue
+ private Integer id;
+ private String name;
+ private Integer age;
+ private ZonedDateTime birthDate;
+ private Boolean active;
+
+ public User() {
+ }
+
+ public User(String name, Integer age, ZonedDateTime birthDate, Boolean active) {
+ this.name = name;
+ this.age = age;
+ this.birthDate = birthDate;
+ this.active = active;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ public ZonedDateTime getBirthDate() {
+ return birthDate;
+ }
+
+ public void setBirthDate(ZonedDateTime birthDate) {
+ this.birthDate = birthDate;
+ }
+
+ public Boolean getActive() {
+ return active;
+ }
+
+ public void setActive(Boolean active) {
+ this.active = active;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/repository/UserRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/repository/UserRepository.java
new file mode 100644
index 0000000000..a23855d96d
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/derivedquery/repository/UserRepository.java
@@ -0,0 +1,60 @@
+package com.baeldung.derivedquery.repository;
+
+import com.baeldung.derivedquery.entity.User;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.time.ZonedDateTime;
+import java.util.Collection;
+import java.util.List;
+
+public interface UserRepository extends JpaRepository {
+
+ List findByName(String name);
+
+ List findByNameIs(String name);
+
+ List findByNameEquals(String name);
+
+ List findByNameIsNull();
+
+ List findByNameNot(String name);
+
+ List findByNameIsNot(String name);
+
+ List findByNameStartingWith(String name);
+
+ List findByNameEndingWith(String name);
+
+ List findByNameContaining(String name);
+
+ List findByNameLike(String name);
+
+ List findByAgeLessThan(Integer age);
+
+ List findByAgeLessThanEqual(Integer age);
+
+ List findByAgeGreaterThan(Integer age);
+
+ List findByAgeGreaterThanEqual(Integer age);
+
+ List findByAgeBetween(Integer startAge, Integer endAge);
+
+ List findByBirthDateAfter(ZonedDateTime birthDate);
+
+ List findByBirthDateBefore(ZonedDateTime birthDate);
+
+ List findByActiveTrue();
+
+ List findByActiveFalse();
+
+ List findByAgeIn(Collection ages);
+
+ List findByNameOrBirthDate(String name, ZonedDateTime birthDate);
+
+ List findByNameOrBirthDateAndActive(String name, ZonedDateTime birthDate, Boolean active);
+
+ List findByNameOrderByName(String name);
+
+ List findByNameOrderByNameDesc(String name);
+
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/derivedquery/repository/UserRepositoryTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/derivedquery/repository/UserRepositoryTest.java
new file mode 100644
index 0000000000..188ed5d4d0
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/derivedquery/repository/UserRepositoryTest.java
@@ -0,0 +1,172 @@
+package com.baeldung.derivedquery.repository;
+
+import com.baeldung.Application;
+import com.baeldung.derivedquery.entity.User;
+import com.baeldung.derivedquery.repository.UserRepository;
+import java.time.ZonedDateTime;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class UserRepositoryTest {
+
+ private static final String USER_NAME_ADAM = "Adam";
+ private static final String USER_NAME_EVE = "Eve";
+ private static final ZonedDateTime BIRTHDATE = ZonedDateTime.now();
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Before
+ public void setUp() {
+
+ User user1 = new User(USER_NAME_ADAM, 25, BIRTHDATE, true);
+ User user2 = new User(USER_NAME_ADAM, 20, BIRTHDATE, false);
+ User user3 = new User(USER_NAME_EVE, 20, BIRTHDATE, true);
+ User user4 = new User(null, 30, BIRTHDATE, false);
+
+ userRepository.saveAll(Arrays.asList(user1, user2, user3, user4));
+ }
+
+ @After
+ public void tearDown() {
+
+ userRepository.deleteAll();
+ }
+
+ @Test
+ public void whenFindByName_thenReturnsCorrectResult() {
+
+ assertEquals(2, userRepository.findByName(USER_NAME_ADAM).size());
+ }
+
+ @Test
+ public void whenFindByNameIsNull_thenReturnsCorrectResult() {
+
+ assertEquals(1, userRepository.findByNameIsNull().size());
+ }
+
+ @Test
+ public void whenFindByNameNot_thenReturnsCorrectResult() {
+
+ assertEquals(USER_NAME_EVE, userRepository.findByNameNot(USER_NAME_ADAM).get(0).getName());
+ }
+
+ @Test
+ public void whenFindByNameStartingWith_thenReturnsCorrectResult() {
+
+ assertEquals(2, userRepository.findByNameStartingWith("A").size());
+ }
+
+ @Test
+ public void whenFindByNameEndingWith_thenReturnsCorrectResult() {
+
+ assertEquals(1, userRepository.findByNameEndingWith("e").size());
+ }
+
+ @Test
+ public void whenByNameContaining_thenReturnsCorrectResult() {
+
+ assertEquals(1, userRepository.findByNameContaining("v").size());
+ }
+
+
+ @Test
+ public void whenByNameLike_thenReturnsCorrectResult() {
+
+ assertEquals(2, userRepository.findByNameEndingWith("%d%m").size());
+ }
+
+ @Test
+ public void whenByAgeLessThan_thenReturnsCorrectResult() {
+
+ assertEquals(2, userRepository.findByAgeLessThan(25).size());
+ }
+
+
+ @Test
+ public void whenByAgeLessThanEqual_thenReturnsCorrectResult() {
+
+ assertEquals(3, userRepository.findByAgeLessThanEqual(25).size());
+ }
+
+ @Test
+ public void whenByAgeGreaterThan_thenReturnsCorrectResult() {
+
+ assertEquals(1, userRepository.findByAgeGreaterThan(25).size());
+ }
+
+ @Test
+ public void whenByAgeGreaterThanEqual_thenReturnsCorrectResult() {
+
+ assertEquals(2, userRepository.findByAgeGreaterThanEqual(25).size());
+ }
+
+ @Test
+ public void whenByAgeBetween_thenReturnsCorrectResult() {
+
+ assertEquals(4, userRepository.findByAgeBetween(20, 30).size());
+ }
+
+ @Test
+ public void whenByBirthDateAfter_thenReturnsCorrectResult() {
+
+ final ZonedDateTime yesterday = BIRTHDATE.minusDays(1);
+ assertEquals(4, userRepository.findByBirthDateAfter(yesterday).size());
+ }
+
+ @Test
+ public void whenByBirthDateBefore_thenReturnsCorrectResult() {
+
+ final ZonedDateTime yesterday = BIRTHDATE.minusDays(1);
+ assertEquals(0, userRepository.findByBirthDateBefore(yesterday).size());
+ }
+
+ @Test
+ public void whenByActiveTrue_thenReturnsCorrectResult() {
+
+ assertEquals(2, userRepository.findByActiveTrue().size());
+ }
+
+ @Test
+ public void whenByActiveFalse_thenReturnsCorrectResult() {
+
+ assertEquals(2, userRepository.findByActiveFalse().size());
+ }
+
+
+ @Test
+ public void whenByAgeIn_thenReturnsCorrectResult() {
+
+ final List ages = Arrays.asList(20, 25);
+ assertEquals(3, userRepository.findByAgeIn(ages).size());
+ }
+
+ @Test
+ public void whenByNameOrBirthDate() {
+
+ assertEquals(4, userRepository.findByNameOrBirthDate(USER_NAME_ADAM, BIRTHDATE).size());
+ }
+
+ @Test
+ public void whenByNameOrBirthDateAndActive() {
+
+ assertEquals(3, userRepository.findByNameOrBirthDateAndActive(USER_NAME_ADAM, BIRTHDATE, false).size());
+ }
+
+ @Test
+ public void whenByNameOrderByName() {
+
+ assertEquals(2, userRepository.findByNameOrderByName(USER_NAME_ADAM).size());
+ }
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa/README.md b/persistence-modules/spring-data-jpa/README.md
index 4e390c2faf..e85d8a8487 100644
--- a/persistence-modules/spring-data-jpa/README.md
+++ b/persistence-modules/spring-data-jpa/README.md
@@ -6,7 +6,6 @@
- [Spring JPA – Multiple Databases](http://www.baeldung.com/spring-data-jpa-multiple-databases)
- [Spring Data JPA – Adding a Method in All Repositories](http://www.baeldung.com/spring-data-jpa-method-in-all-repositories)
- [An Advanced Tagging Implementation with JPA](http://www.baeldung.com/jpa-tagging-advanced)
-- [Spring Data JPA @Query](http://www.baeldung.com/spring-data-jpa-query)
- [Spring Data Annotations](http://www.baeldung.com/spring-data-annotations)
- [Spring Data Java 8 Support](http://www.baeldung.com/spring-data-java-8)
- [A Simple Tagging Implementation with JPA](http://www.baeldung.com/jpa-tagging)
diff --git a/persistence-modules/spring-hibernate4/README.md b/persistence-modules/spring-hibernate4/README.md
index f2553ad229..6f8d83aa9d 100644
--- a/persistence-modules/spring-hibernate4/README.md
+++ b/persistence-modules/spring-hibernate4/README.md
@@ -4,7 +4,6 @@
### Relevant Articles:
- [Guide to Hibernate 4 with Spring](http://www.baeldung.com/hibernate-4-spring)
-- [The DAO with Spring and Hibernate](http://www.baeldung.com/persistence-layer-with-spring-and-hibernate)
- [Hibernate Pagination](http://www.baeldung.com/hibernate-pagination)
- [Sorting with Hibernate](http://www.baeldung.com/hibernate-sort)
- [Stored Procedures with Hibernate](http://www.baeldung.com/stored-procedures-with-hibernate-tutorial)
diff --git a/persistence-modules/spring-jpa/README.md b/persistence-modules/spring-jpa/README.md
index 2f2a27e4ac..e856e4808e 100644
--- a/persistence-modules/spring-jpa/README.md
+++ b/persistence-modules/spring-jpa/README.md
@@ -4,8 +4,6 @@
### Relevant Articles:
-- [A Guide to JPA with Spring](https://www.baeldung.com/the-persistence-layer-with-spring-and-jpa)
-- [Transactions with Spring and JPA](https://www.baeldung.com/transaction-configuration-with-jpa-and-spring)
- [The DAO with JPA and Spring](http://www.baeldung.com/spring-dao-jpa)
- [JPA Pagination](http://www.baeldung.com/jpa-pagination)
- [Sorting with JPA](http://www.baeldung.com/jpa-sort)
diff --git a/persistence-modules/spring-persistence-simple/.gitignore b/persistence-modules/spring-persistence-simple/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/README.md b/persistence-modules/spring-persistence-simple/README.md
new file mode 100644
index 0000000000..c656efaa3b
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/README.md
@@ -0,0 +1,24 @@
+=========
+
+## Spring Persistence Example Project
+
+
+### Relevant Articles:
+- [A Guide to JPA with Spring](https://www.baeldung.com/the-persistence-layer-with-spring-and-jpa)
+- [Bootstrapping Hibernate 5 with Spring](http://www.baeldung.com/hibernate-5-spring)
+- [The DAO with Spring and Hibernate](http://www.baeldung.com/persistence-layer-with-spring-and-hibernate)
+- [DAO with Spring and Generics](https://www.baeldung.com/simplifying-the-data-access-layer-with-spring-and-java-generics)
+- [Transactions with Spring and JPA](https://www.baeldung.com/transaction-configuration-with-jpa-and-spring)
+- [Introduction to Spring Data JPA](http://www.baeldung.com/the-persistence-layer-with-spring-data-jpa)
+- [Spring Data JPA @Query](http://www.baeldung.com/spring-data-jpa-query)
+
+
+### Eclipse Config
+After importing the project into Eclipse, you may see the following error:
+"No persistence xml file found in project"
+
+This can be ignored:
+- Project -> Properties -> Java Persistance -> JPA -> Error/Warnings -> Select Ignore on "No persistence xml file found in project"
+Or:
+- Eclipse -> Preferences - Validation - disable the "Build" execution of the JPA Validator
+
diff --git a/persistence-modules/spring-persistence-simple/pom.xml b/persistence-modules/spring-persistence-simple/pom.xml
new file mode 100644
index 0000000000..5f48b267b5
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/pom.xml
@@ -0,0 +1,160 @@
+
+ 4.0.0
+ spring-persistence-simple
+ 0.1-SNAPSHOT
+ spring-persistence-simple
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+ ../../
+
+
+
+
+
+ org.springframework
+ spring-orm
+ ${org.springframework.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ org.springframework
+ spring-context
+ ${org.springframework.version}
+
+
+
+
+ org.hibernate
+ hibernate-core
+ ${hibernate.version}
+
+
+ javax.transaction
+ jta
+ ${jta.version}
+
+
+ org.hibernate
+ hibernate-entitymanager
+ ${hibernate.version}
+
+
+ mysql
+ mysql-connector-java
+ ${mysql-connector-java.version}
+ runtime
+
+
+ org.springframework.data
+ spring-data-jpa
+ ${spring-data-jpa.version}
+
+
+ com.h2database
+ h2
+ ${h2.version}
+
+
+
+ org.apache.tomcat
+ tomcat-dbcp
+ ${tomcat-dbcp.version}
+
+
+
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+ test
+
+
+
+ org.springframework
+ spring-test
+ ${org.springframework.version}
+ test
+
+
+ com.querydsl
+ querydsl-jpa
+ ${querydsl.version}
+
+
+ com.querydsl
+ querydsl-apt
+ ${querydsl.version}
+
+
+
+
+ spring-persistence-simple
+
+
+ src/main/resources
+ true
+
+
+
+
+ com.mysema.maven
+ apt-maven-plugin
+ 1.1.3
+
+
+ generate-sources
+
+ process
+
+
+ target/generated-sources
+ com.querydsl.apt.jpa.JPAAnnotationProcessor
+
+
+
+
+
+
+
+
+
+ 5.1.6.RELEASE
+
+
+ 5.4.2.Final
+ 6.0.6
+ 2.1.6.RELEASE
+ 9.0.0.M26
+ 1.1
+ 4.2.1
+
+
+ 21.0
+ 3.5
+ 3.8.0
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/BarHibernateDAO.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/BarHibernateDAO.java
new file mode 100644
index 0000000000..5fc932b256
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/BarHibernateDAO.java
@@ -0,0 +1,39 @@
+package com.baeldung.hibernate.bootstrap;
+
+import com.baeldung.hibernate.bootstrap.model.TestEntity;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public abstract class BarHibernateDAO {
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ public TestEntity findEntity(int id) {
+
+ return getCurrentSession().find(TestEntity.class, 1);
+ }
+
+ public void createEntity(TestEntity entity) {
+
+ getCurrentSession().save(entity);
+ }
+
+ public void createEntity(int id, String newDescription) {
+
+ TestEntity entity = findEntity(id);
+ entity.setDescription(newDescription);
+ getCurrentSession().save(entity);
+ }
+
+ public void deleteEntity(int id) {
+
+ TestEntity entity = findEntity(id);
+ getCurrentSession().delete(entity);
+ }
+
+ protected Session getCurrentSession() {
+ return sessionFactory.getCurrentSession();
+ }
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateConf.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateConf.java
new file mode 100644
index 0000000000..150e3778af
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateConf.java
@@ -0,0 +1,61 @@
+package com.baeldung.hibernate.bootstrap;
+
+import com.google.common.base.Preconditions;
+import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.core.env.Environment;
+import org.springframework.orm.hibernate5.HibernateTransactionManager;
+import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.sql.DataSource;
+import java.util.Properties;
+
+@Configuration
+@EnableTransactionManagement
+@PropertySource({ "classpath:persistence-h2.properties" })
+public class HibernateConf {
+
+ @Autowired
+ private Environment env;
+
+ @Bean
+ public LocalSessionFactoryBean sessionFactory() {
+ final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
+ sessionFactory.setDataSource(dataSource());
+ sessionFactory.setPackagesToScan(new String[] { "com.baeldung.hibernate.bootstrap.model" });
+ sessionFactory.setHibernateProperties(hibernateProperties());
+
+ return sessionFactory;
+ }
+
+ @Bean
+ public DataSource dataSource() {
+ final BasicDataSource dataSource = new BasicDataSource();
+ dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
+ dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
+ dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
+ dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
+
+ return dataSource;
+ }
+
+ @Bean
+ public PlatformTransactionManager hibernateTransactionManager() {
+ final HibernateTransactionManager transactionManager = new HibernateTransactionManager();
+ transactionManager.setSessionFactory(sessionFactory().getObject());
+ return transactionManager;
+ }
+
+ private final Properties hibernateProperties() {
+ final Properties hibernateProperties = new Properties();
+ hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
+ hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
+
+ return hibernateProperties;
+ }
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateXMLConf.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateXMLConf.java
new file mode 100644
index 0000000000..b3e979478f
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/HibernateXMLConf.java
@@ -0,0 +1,24 @@
+package com.baeldung.hibernate.bootstrap;
+
+import com.google.common.base.Preconditions;
+import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.ImportResource;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.core.env.Environment;
+import org.springframework.orm.hibernate5.HibernateTransactionManager;
+import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.sql.DataSource;
+import java.util.Properties;
+
+@Configuration
+@EnableTransactionManagement
+@ImportResource({ "classpath:hibernate5Configuration.xml" })
+public class HibernateXMLConf {
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/model/TestEntity.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/model/TestEntity.java
new file mode 100644
index 0000000000..cae41db831
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/hibernate/bootstrap/model/TestEntity.java
@@ -0,0 +1,29 @@
+package com.baeldung.hibernate.bootstrap.model;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+public class TestEntity {
+
+ private int id;
+
+ private String description;
+
+ @Id
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java
new file mode 100644
index 0000000000..5a6c76a93a
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java
@@ -0,0 +1,14 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractDao implements IOperations {
+
+ protected Class clazz;
+
+ protected final void setClazz(final Class clazzToSet) {
+ clazz = Preconditions.checkNotNull(clazzToSet);
+ }
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java
new file mode 100644
index 0000000000..e406f896dc
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java
@@ -0,0 +1,60 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.google.common.base.Preconditions;
+
+@SuppressWarnings("unchecked")
+public abstract class AbstractHibernateDao extends AbstractDao implements IOperations {
+
+ @Autowired
+ protected SessionFactory sessionFactory;
+
+ // API
+
+ @Override
+ public T findOne(final long id) {
+ return (T) getCurrentSession().get(clazz, id);
+ }
+
+ @Override
+ public List findAll() {
+ return getCurrentSession().createQuery("from " + clazz.getName()).list();
+ }
+
+ @Override
+ public T create(final T entity) {
+ Preconditions.checkNotNull(entity);
+ getCurrentSession().saveOrUpdate(entity);
+ return entity;
+ }
+
+ @Override
+ public T update(final T entity) {
+ Preconditions.checkNotNull(entity);
+ return (T) getCurrentSession().merge(entity);
+ }
+
+ @Override
+ public void delete(final T entity) {
+ Preconditions.checkNotNull(entity);
+ getCurrentSession().delete(entity);
+ }
+
+ @Override
+ public void deleteById(final long entityId) {
+ final T entity = findOne(entityId);
+ Preconditions.checkState(entity != null);
+ delete(entity);
+ }
+
+ protected Session getCurrentSession() {
+ return sessionFactory.getCurrentSession();
+ }
+
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java
new file mode 100644
index 0000000000..18b16fa033
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java
@@ -0,0 +1,13 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Repository;
+
+@Repository
+@Scope(BeanDefinition.SCOPE_PROTOTYPE)
+public class GenericHibernateDao extends AbstractHibernateDao implements IGenericDao {
+ //
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericJpaDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericJpaDao.java
new file mode 100644
index 0000000000..5bcebed761
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/GenericJpaDao.java
@@ -0,0 +1,14 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+
+import org.baeldung.persistence.dao.AbstractJpaDAO;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Repository;
+
+@Repository
+@Scope(BeanDefinition.SCOPE_PROTOTYPE)
+public class GenericJpaDao extends AbstractJpaDAO implements IGenericDao {
+ //
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java
new file mode 100644
index 0000000000..8d8af18394
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java
@@ -0,0 +1,7 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+
+public interface IGenericDao extends IOperations {
+ //
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IOperations.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IOperations.java
new file mode 100644
index 0000000000..34c5e0f616
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/common/IOperations.java
@@ -0,0 +1,20 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+public interface IOperations {
+
+ T findOne(final long id);
+
+ List findAll();
+
+ T create(final T entity);
+
+ T update(final T entity);
+
+ void delete(final T entity);
+
+ void deleteById(final long entityId);
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java
new file mode 100644
index 0000000000..2d940527e1
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java
@@ -0,0 +1,20 @@
+package com.baeldung.persistence.dao.impl;
+
+import org.baeldung.persistence.dao.IFooDao;
+import org.baeldung.persistence.model.Foo;
+import org.springframework.stereotype.Repository;
+
+import com.baeldung.persistence.dao.common.AbstractHibernateDao;
+
+@Repository
+public class FooDao extends AbstractHibernateDao implements IFooDao {
+
+ public FooDao() {
+ super();
+
+ setClazz(Foo.class);
+ }
+
+ // API
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceConfig.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceConfig.java
new file mode 100644
index 0000000000..c454ab3b54
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceConfig.java
@@ -0,0 +1,118 @@
+package org.baeldung.config;
+
+import java.util.Properties;
+
+import javax.sql.DataSource;
+
+import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
+import org.baeldung.persistence.dao.IFooDao;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.core.env.Environment;
+import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.orm.hibernate5.HibernateTransactionManager;
+import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
+import org.springframework.orm.jpa.JpaTransactionManager;
+import org.springframework.orm.jpa.JpaVendorAdapter;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import com.baeldung.persistence.dao.impl.FooDao;
+import com.google.common.base.Preconditions;
+
+@Configuration
+@EnableTransactionManagement
+@EnableJpaRepositories(basePackages = { "com.baeldung.persistence" }, transactionManagerRef = "jpaTransactionManager")
+@EnableJpaAuditing
+@PropertySource({ "classpath:persistence-mysql.properties" })
+@ComponentScan({ "com.baeldung.persistence" })
+public class PersistenceConfig {
+
+ @Autowired
+ private Environment env;
+
+ public PersistenceConfig() {
+ super();
+ }
+
+ @Bean
+ public LocalSessionFactoryBean sessionFactory() {
+ final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
+ sessionFactory.setDataSource(restDataSource());
+ sessionFactory.setPackagesToScan(new String[] { "com.baeldung.persistence.model" });
+ sessionFactory.setHibernateProperties(hibernateProperties());
+
+ return sessionFactory;
+ }
+
+ @Bean
+ public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
+ final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
+ emf.setDataSource(restDataSource());
+ emf.setPackagesToScan(new String[] { "com.baeldung.persistence.model" });
+
+ final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
+ emf.setJpaVendorAdapter(vendorAdapter);
+ emf.setJpaProperties(hibernateProperties());
+
+ return emf;
+ }
+
+ @Bean
+ public DataSource restDataSource() {
+ final BasicDataSource dataSource = new BasicDataSource();
+ dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
+ dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
+ dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
+ dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
+
+ return dataSource;
+ }
+
+ @Bean
+ public PlatformTransactionManager hibernateTransactionManager() {
+ final HibernateTransactionManager transactionManager = new HibernateTransactionManager();
+ transactionManager.setSessionFactory(sessionFactory().getObject());
+ return transactionManager;
+ }
+
+ @Bean
+ public PlatformTransactionManager jpaTransactionManager() {
+ final JpaTransactionManager transactionManager = new JpaTransactionManager();
+ transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
+ return transactionManager;
+ }
+
+ @Bean
+ public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
+ return new PersistenceExceptionTranslationPostProcessor();
+ }
+
+ @Bean
+ public IFooDao fooHibernateDao() {
+ return new FooDao();
+ }
+
+ private final Properties hibernateProperties() {
+ final Properties hibernateProperties = new Properties();
+ hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
+ hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
+
+ hibernateProperties.setProperty("hibernate.show_sql", "true");
+ // hibernateProperties.setProperty("hibernate.format_sql", "true");
+ // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true");
+
+ // Envers properties
+ hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", env.getProperty("envers.audit_table_suffix"));
+
+ return hibernateProperties;
+ }
+
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceJPAConfig.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceJPAConfig.java
new file mode 100644
index 0000000000..ec0d4bca3c
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/config/PersistenceJPAConfig.java
@@ -0,0 +1,87 @@
+package org.baeldung.config;
+
+import java.util.Properties;
+
+import javax.persistence.EntityManagerFactory;
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.core.env.Environment;
+import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+import org.springframework.orm.jpa.JpaTransactionManager;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import com.google.common.base.Preconditions;
+
+@Configuration
+@EnableTransactionManagement
+@PropertySource({ "classpath:persistence-h2.properties" })
+@ComponentScan({ "org.baeldung.persistence" })
+@EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao")
+public class PersistenceJPAConfig {
+
+ @Autowired
+ private Environment env;
+
+ public PersistenceJPAConfig() {
+ super();
+ }
+
+ // beans
+
+ @Bean
+ public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
+ final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
+ em.setDataSource(dataSource());
+ em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" });
+
+ final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
+ em.setJpaVendorAdapter(vendorAdapter);
+ em.setJpaProperties(additionalProperties());
+
+ return em;
+ }
+
+ @Bean
+ public DataSource dataSource() {
+ final DriverManagerDataSource dataSource = new DriverManagerDataSource();
+ dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
+ dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
+ dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
+ dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
+
+ return dataSource;
+ }
+
+ @Bean
+ public PlatformTransactionManager transactionManager(final EntityManagerFactory emf) {
+ final JpaTransactionManager transactionManager = new JpaTransactionManager();
+ transactionManager.setEntityManagerFactory(emf);
+ return transactionManager;
+ }
+
+ @Bean
+ public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
+ return new PersistenceExceptionTranslationPostProcessor();
+ }
+
+ final Properties additionalProperties() {
+ final Properties hibernateProperties = new Properties();
+ hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
+ hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
+ hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", "false");
+
+
+ return hibernateProperties;
+ }
+
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/AbstractJpaDAO.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/AbstractJpaDAO.java
new file mode 100644
index 0000000000..decca35c08
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/AbstractJpaDAO.java
@@ -0,0 +1,47 @@
+package org.baeldung.persistence.dao;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+public abstract class AbstractJpaDAO {
+
+ private Class clazz;
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ public final void setClazz(final Class clazzToSet) {
+ this.clazz = clazzToSet;
+ }
+
+ public T findOne(final long id) {
+ return entityManager.find(clazz, id);
+ }
+
+ @SuppressWarnings("unchecked")
+ public List findAll() {
+ return entityManager.createQuery("from " + clazz.getName()).getResultList();
+ }
+
+ public T create(final T entity) {
+ entityManager.persist(entity);
+ return entity;
+ }
+
+ public T update(final T entity) {
+ return entityManager.merge(entity);
+ }
+
+ public void delete(final T entity) {
+ entityManager.remove(entity);
+ }
+
+ public void deleteById(final long entityId) {
+ final T entity = findOne(entityId);
+ delete(entity);
+ }
+
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/FooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/FooDao.java
new file mode 100644
index 0000000000..77978c5cf2
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/FooDao.java
@@ -0,0 +1,17 @@
+package org.baeldung.persistence.dao;
+
+import org.baeldung.persistence.model.Foo;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class FooDao extends AbstractJpaDAO implements IFooDao {
+
+ public FooDao() {
+ super();
+
+ setClazz(Foo.class);
+ }
+
+ // API
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/IFooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/IFooDao.java
new file mode 100644
index 0000000000..ba188b9b3a
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/dao/IFooDao.java
@@ -0,0 +1,21 @@
+package org.baeldung.persistence.dao;
+
+import java.util.List;
+
+import org.baeldung.persistence.model.Foo;
+
+public interface IFooDao {
+
+ Foo findOne(long id);
+
+ List findAll();
+
+ Foo create(Foo entity);
+
+ Foo update(Foo entity);
+
+ void delete(Foo entity);
+
+ void deleteById(long entityId);
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Bar.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Bar.java
new file mode 100644
index 0000000000..b602e57562
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Bar.java
@@ -0,0 +1,102 @@
+package org.baeldung.persistence.model;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.OrderBy;
+
+@Entity
+public class Bar implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long id;
+
+ @Column(nullable = false)
+ private String name;
+
+ @OneToMany(mappedBy = "bar", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
+ @OrderBy("name ASC")
+ List fooList;
+
+ public Bar() {
+ super();
+ }
+
+ public Bar(final String name) {
+ super();
+
+ this.name = name;
+ }
+
+ // API
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(final long id) {
+
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public List getFooList() {
+ return fooList;
+ }
+
+ public void setFooList(final List fooList) {
+ this.fooList = fooList;
+ }
+
+ //
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Bar other = (Bar) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Bar [name=").append(name).append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Foo.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Foo.java
new file mode 100644
index 0000000000..30635e9ef2
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/model/Foo.java
@@ -0,0 +1,104 @@
+package org.baeldung.persistence.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedNativeQueries;
+import javax.persistence.NamedNativeQuery;
+
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+
+@Entity
+@Cacheable
+@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
+@NamedNativeQueries({ @NamedNativeQuery(name = "callGetAllFoos", query = "CALL GetAllFoos()", resultClass = Foo.class), @NamedNativeQuery(name = "callGetFoosByName", query = "CALL GetFoosByName(:fooName)", resultClass = Foo.class) })
+public class Foo implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ public Foo() {
+ super();
+ }
+
+ public Foo(final String name) {
+ super();
+
+ this.name = name;
+ }
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(name = "ID")
+ private Long id;
+ @Column(name = "NAME")
+ private String name;
+
+ @ManyToOne(targetEntity = Bar.class, fetch = FetchType.EAGER)
+ @JoinColumn(name = "BAR_ID")
+ private Bar bar;
+
+ public Bar getBar() {
+ return bar;
+ }
+
+ public void setBar(final Bar bar) {
+ this.bar = bar;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(final Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Foo other = (Foo) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Foo [name=").append(name).append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/service/FooService.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/service/FooService.java
new file mode 100644
index 0000000000..6d1bb0adbe
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/persistence/service/FooService.java
@@ -0,0 +1,36 @@
+package org.baeldung.persistence.service;
+
+import java.util.List;
+
+import org.baeldung.persistence.dao.IFooDao;
+import org.baeldung.persistence.model.Foo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@Transactional
+public class FooService {
+
+ @Autowired
+ private IFooDao dao;
+
+ public FooService() {
+ super();
+ }
+
+ // API
+
+ public void create(final Foo entity) {
+ dao.create(entity);
+ }
+
+ public Foo findOne(final long id) {
+ return dao.findOne(id);
+ }
+
+ public List findAll() {
+ return dao.findAll();
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/config/PersistenceConfig.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/config/PersistenceConfig.java
new file mode 100644
index 0000000000..067bac2018
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/config/PersistenceConfig.java
@@ -0,0 +1,85 @@
+package org.baeldung.spring.data.persistence.config;
+
+import java.util.Properties;
+
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.core.env.Environment;
+import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+import org.springframework.orm.jpa.JpaTransactionManager;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import com.google.common.base.Preconditions;
+
+@Configuration
+@EnableTransactionManagement
+@PropertySource({ "classpath:persistence-${envTarget:h2}.properties" })
+@ComponentScan({ "org.baeldung.spring.data.persistence" })
+// @ImportResource("classpath*:springDataPersistenceConfig.xml")
+@EnableJpaRepositories(basePackages = "org.baeldung.spring.data.persistence.dao")
+public class PersistenceConfig {
+
+ @Autowired
+ private Environment env;
+
+ public PersistenceConfig() {
+ super();
+ }
+
+ @Bean
+ public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
+ final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
+ em.setDataSource(dataSource());
+ em.setPackagesToScan(new String[] { "org.baeldung.spring.data.persistence.model" });
+
+ final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
+ // vendorAdapter.set
+ em.setJpaVendorAdapter(vendorAdapter);
+ em.setJpaProperties(additionalProperties());
+
+ return em;
+ }
+
+ @Bean
+ public DataSource dataSource() {
+ final DriverManagerDataSource dataSource = new DriverManagerDataSource();
+ dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
+ dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
+ dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
+ dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
+
+ return dataSource;
+ }
+
+ @Bean
+ public PlatformTransactionManager transactionManager() {
+ final JpaTransactionManager transactionManager = new JpaTransactionManager();
+ transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
+
+ return transactionManager;
+ }
+
+ @Bean
+ public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
+ return new PersistenceExceptionTranslationPostProcessor();
+ }
+
+ final Properties additionalProperties() {
+ final Properties hibernateProperties = new Properties();
+ hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
+ hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
+ // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true");
+ return hibernateProperties;
+ }
+
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/IFooDao.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/IFooDao.java
new file mode 100644
index 0000000000..2f74096e14
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/IFooDao.java
@@ -0,0 +1,11 @@
+package org.baeldung.spring.data.persistence.dao;
+
+import org.baeldung.spring.data.persistence.model.Foo;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+public interface IFooDao extends JpaRepository {
+
+ @Query("SELECT f FROM Foo f WHERE LOWER(f.name) = LOWER(:name)")
+ Foo retrieveByName(@Param("name") String name);
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepository.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepository.java
new file mode 100644
index 0000000000..4d01376af7
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepository.java
@@ -0,0 +1,98 @@
+package org.baeldung.spring.data.persistence.dao.user;
+
+import java.time.LocalDate;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.baeldung.spring.data.persistence.model.User;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+public interface UserRepository extends JpaRepository, UserRepositoryCustom {
+
+ Stream findAllByName(String name);
+
+ @Query("SELECT u FROM User u WHERE u.status = 1")
+ Collection findAllActiveUsers();
+
+ @Query("select u from User u where u.email like '%@gmail.com'")
+ List findUsersWithGmailAddress();
+
+ @Query(value = "SELECT * FROM Users u WHERE u.status = 1", nativeQuery = true)
+ Collection findAllActiveUsersNative();
+
+ @Query("SELECT u FROM User u WHERE u.status = ?1")
+ User findUserByStatus(Integer status);
+
+ @Query(value = "SELECT * FROM Users u WHERE u.status = ?1", nativeQuery = true)
+ User findUserByStatusNative(Integer status);
+
+ @Query("SELECT u FROM User u WHERE u.status = ?1 and u.name = ?2")
+ User findUserByStatusAndName(Integer status, String name);
+
+ @Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name")
+ User findUserByStatusAndNameNamedParams(@Param("status") Integer status, @Param("name") String name);
+
+ @Query(value = "SELECT * FROM Users u WHERE u.status = :status AND u.name = :name", nativeQuery = true)
+ User findUserByStatusAndNameNamedParamsNative(@Param("status") Integer status, @Param("name") String name);
+
+ @Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name")
+ User findUserByUserStatusAndUserName(@Param("status") Integer userStatus, @Param("name") String userName);
+
+ @Query("SELECT u FROM User u WHERE u.name like ?1%")
+ User findUserByNameLike(String name);
+
+ @Query("SELECT u FROM User u WHERE u.name like :name%")
+ User findUserByNameLikeNamedParam(@Param("name") String name);
+
+ @Query(value = "SELECT * FROM users u WHERE u.name LIKE ?1%", nativeQuery = true)
+ User findUserByNameLikeNative(String name);
+
+ @Query(value = "SELECT u FROM User u")
+ List findAllUsers(Sort sort);
+
+ @Query(value = "SELECT u FROM User u ORDER BY id")
+ Page findAllUsersWithPagination(Pageable pageable);
+
+ @Query(value = "SELECT * FROM Users ORDER BY id", countQuery = "SELECT count(*) FROM Users", nativeQuery = true)
+ Page findAllUsersWithPaginationNative(Pageable pageable);
+
+ @Modifying
+ @Query("update User u set u.status = :status where u.name = :name")
+ int updateUserSetStatusForName(@Param("status") Integer status, @Param("name") String name);
+
+ @Modifying
+ @Query(value = "UPDATE Users u SET u.status = ? WHERE u.name = ?", nativeQuery = true)
+ int updateUserSetStatusForNameNative(Integer status, String name);
+
+ @Query(value = "INSERT INTO Users (name, age, email, status, active) VALUES (:name, :age, :email, :status, :active)", nativeQuery = true)
+ @Modifying
+ void insertUser(@Param("name") String name, @Param("age") Integer age, @Param("email") String email, @Param("status") Integer status, @Param("active") boolean active);
+
+ @Modifying
+ @Query(value = "UPDATE Users u SET status = ? WHERE u.name = ?", nativeQuery = true)
+ int updateUserSetStatusForNameNativePostgres(Integer status, String name);
+
+ @Query(value = "SELECT u FROM User u WHERE u.name IN :names")
+ List findUserByNameList(@Param("names") Collection names);
+
+ void deleteAllByCreationDateAfter(LocalDate date);
+
+ @Modifying(clearAutomatically = true, flushAutomatically = true)
+ @Query("update User u set u.active = false where u.lastLoginDate < :date")
+ void deactivateUsersNotLoggedInSince(@Param("date") LocalDate date);
+
+ @Modifying(clearAutomatically = true, flushAutomatically = true)
+ @Query("delete User u where u.active = false")
+ int deleteDeactivatedUsers();
+
+ @Modifying(clearAutomatically = true, flushAutomatically = true)
+ @Query(value = "alter table USERS add column deleted int(1) not null default 0", nativeQuery = true)
+ void addDeletedColumn();
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustom.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustom.java
new file mode 100644
index 0000000000..1a874fb5e5
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustom.java
@@ -0,0 +1,14 @@
+package org.baeldung.spring.data.persistence.dao.user;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Predicate;
+
+import org.baeldung.spring.data.persistence.model.User;
+
+public interface UserRepositoryCustom {
+ List findUserByEmails(Set emails);
+
+ List findAllUsersByPredicates(Collection> predicates);
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustomImpl.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustomImpl.java
new file mode 100644
index 0000000000..c28050401c
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCustomImpl.java
@@ -0,0 +1,57 @@
+package org.baeldung.spring.data.persistence.dao.user;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Path;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+
+import org.baeldung.spring.data.persistence.model.User;
+
+public class UserRepositoryCustomImpl implements UserRepositoryCustom {
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ @Override
+ public List findUserByEmails(Set emails) {
+ CriteriaBuilder cb = entityManager.getCriteriaBuilder();
+ CriteriaQuery query = cb.createQuery(User.class);
+ Root user = query.from(User.class);
+
+ Path emailPath = user.get("email");
+
+ List predicates = new ArrayList<>();
+ for (String email : emails) {
+
+ predicates.add(cb.like(emailPath, email));
+
+ }
+ query.select(user)
+ .where(cb.or(predicates.toArray(new Predicate[predicates.size()])));
+
+ return entityManager.createQuery(query)
+ .getResultList();
+ }
+
+ @Override
+ public List findAllUsersByPredicates(Collection> predicates) {
+ List allUsers = entityManager.createQuery("select u from User u", User.class).getResultList();
+ Stream allUsersStream = allUsers.stream();
+ for (java.util.function.Predicate predicate : predicates) {
+ allUsersStream = allUsersStream.filter(predicate);
+ }
+
+ return allUsersStream.collect(Collectors.toList());
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Foo.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Foo.java
new file mode 100644
index 0000000000..8f316ac55b
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Foo.java
@@ -0,0 +1,83 @@
+package org.baeldung.spring.data.persistence.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+public class Foo implements Serializable {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long id;
+
+ @Column(nullable = false)
+ private String name;
+
+ public Foo() {
+ super();
+ }
+
+ public Foo(final String name) {
+ super();
+
+ this.name = name;
+ }
+
+ // API
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ //
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Foo other = (Foo) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Foo [name=").append(name).append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Possession.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Possession.java
new file mode 100644
index 0000000000..da64e78552
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/Possession.java
@@ -0,0 +1,86 @@
+package org.baeldung.spring.data.persistence.model;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table
+public class Possession {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long id;
+
+ private String name;
+
+ public Possession() {
+ super();
+ }
+
+ public Possession(final String name) {
+ super();
+
+ this.name = name;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(final int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = (prime * result) + (int) (id ^ (id >>> 32));
+ result = (prime * result) + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Possession other = (Possession) obj;
+ if (id != other.id) {
+ return false;
+ }
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Possesion [id=").append(id).append(", name=").append(name).append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/User.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/User.java
new file mode 100644
index 0000000000..486ed046e5
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/model/User.java
@@ -0,0 +1,132 @@
+package org.baeldung.spring.data.persistence.model;
+
+import javax.persistence.*;
+
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Objects;
+
+@Entity
+@Table(name = "users")
+public class User {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private int id;
+ private String name;
+ private LocalDate creationDate;
+ private LocalDate lastLoginDate;
+ private boolean active;
+ private int age;
+ @Column(unique = true, nullable = false)
+ private String email;
+ private Integer status;
+ @OneToMany
+ List possessionList;
+
+ public User() {
+ super();
+ }
+
+ public User(String name, LocalDate creationDate,String email, Integer status) {
+ this.name = name;
+ this.creationDate = creationDate;
+ this.email = email;
+ this.status = status;
+ this.active = true;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(final int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(final String email) {
+ this.email = email;
+ }
+
+ public Integer getStatus() {
+ return status;
+ }
+
+ public void setStatus(Integer status) {
+ this.status = status;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(final int age) {
+ this.age = age;
+ }
+
+ public LocalDate getCreationDate() {
+ return creationDate;
+ }
+
+ public List getPossessionList() {
+ return possessionList;
+ }
+
+ public void setPossessionList(List possessionList) {
+ this.possessionList = possessionList;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("User [name=").append(name).append(", id=").append(id).append("]");
+ return builder.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ User user = (User) o;
+ return id == user.id &&
+ age == user.age &&
+ Objects.equals(name, user.name) &&
+ Objects.equals(creationDate, user.creationDate) &&
+ Objects.equals(email, user.email) &&
+ Objects.equals(status, user.status);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, name, creationDate, age, email, status);
+ }
+
+ public LocalDate getLastLoginDate() {
+ return lastLoginDate;
+ }
+
+ public void setLastLoginDate(LocalDate lastLoginDate) {
+ this.lastLoginDate = lastLoginDate;
+ }
+
+ public boolean isActive() {
+ return active;
+ }
+
+ public void setActive(boolean active) {
+ this.active = active;
+ }
+
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/IFooService.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/IFooService.java
new file mode 100644
index 0000000000..26d0171551
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/IFooService.java
@@ -0,0 +1,11 @@
+package org.baeldung.spring.data.persistence.service;
+
+import org.baeldung.spring.data.persistence.model.Foo;
+
+import com.baeldung.persistence.dao.common.IOperations;
+
+public interface IFooService extends IOperations {
+
+ Foo retrieveByName(String name);
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/common/AbstractService.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/common/AbstractService.java
new file mode 100644
index 0000000000..cf28d5e5c6
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/common/AbstractService.java
@@ -0,0 +1,56 @@
+package org.baeldung.spring.data.persistence.service.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.springframework.data.repository.PagingAndSortingRepository;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.baeldung.persistence.dao.common.IOperations;
+import com.google.common.collect.Lists;
+
+@Transactional
+public abstract class AbstractService implements IOperations {
+
+ // read - one
+
+ @Override
+ @Transactional(readOnly = true)
+ public T findOne(final long id) {
+ return getDao().findById(id).orElse(null);
+ }
+
+ // read - all
+
+ @Override
+ @Transactional(readOnly = true)
+ public List findAll() {
+ return Lists.newArrayList(getDao().findAll());
+ }
+
+ // write
+
+ @Override
+ public T create(final T entity) {
+ return getDao().save(entity);
+ }
+
+ @Override
+ public T update(final T entity) {
+ return getDao().save(entity);
+ }
+
+ @Override
+ public void delete(T entity) {
+ getDao().delete(entity);
+ }
+
+ @Override
+ public void deleteById(long entityId) {
+ T entity = findOne(entityId);
+ delete(entity);
+ }
+
+ protected abstract PagingAndSortingRepository getDao();
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/impl/FooService.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/impl/FooService.java
new file mode 100644
index 0000000000..b7ed496df1
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/spring/data/persistence/service/impl/FooService.java
@@ -0,0 +1,38 @@
+package org.baeldung.spring.data.persistence.service.impl;
+
+
+import org.baeldung.spring.data.persistence.model.Foo;
+import org.baeldung.spring.data.persistence.dao.IFooDao;
+import org.baeldung.spring.data.persistence.service.IFooService;
+import org.baeldung.spring.data.persistence.service.common.AbstractService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.repository.PagingAndSortingRepository;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+@Transactional
+public class FooService extends AbstractService implements IFooService {
+
+ @Autowired
+ private IFooDao dao;
+
+ public FooService() {
+ super();
+ }
+
+ // API
+
+ @Override
+ protected PagingAndSortingRepository getDao() {
+ return dao;
+ }
+
+ // custom methods
+
+ @Override
+ public Foo retrieveByName(final String name) {
+ return dao.retrieveByName(name);
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/util/IDUtil.java b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/util/IDUtil.java
new file mode 100644
index 0000000000..85ab623e5f
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/java/org/baeldung/util/IDUtil.java
@@ -0,0 +1,33 @@
+package org.baeldung.util;
+
+import java.util.Random;
+
+public final class IDUtil {
+
+ private IDUtil() {
+ throw new AssertionError();
+ }
+
+ // API
+
+ public static String randomPositiveLongAsString() {
+ return Long.toString(randomPositiveLong());
+ }
+
+ public static String randomNegativeLongAsString() {
+ return Long.toString(randomNegativeLong());
+ }
+
+ public static long randomPositiveLong() {
+ long id = new Random().nextLong() * 10000;
+ id = (id < 0) ? (-1 * id) : id;
+ return id;
+ }
+
+ private static long randomNegativeLong() {
+ long id = new Random().nextLong() * 10000;
+ id = (id > 0) ? (-1 * id) : id;
+ return id;
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Config.xml b/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Config.xml
new file mode 100644
index 0000000000..bbb61cb3e0
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Config.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+ ${hibernate.hbm2ddl.auto}
+ ${hibernate.dialect}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Configuration.xml b/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Configuration.xml
new file mode 100644
index 0000000000..cb6cf0aa5c
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/resources/hibernate5Configuration.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+ ${hibernate.hbm2ddl.auto}
+ ${hibernate.dialect}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/logback.xml b/persistence-modules/spring-persistence-simple/src/main/resources/logback.xml
new file mode 100644
index 0000000000..ec0dc2469a
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/resources/logback.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ web - %date [%thread] %-5level %logger{36} - %message%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/persistence-h2.properties b/persistence-modules/spring-persistence-simple/src/main/resources/persistence-h2.properties
new file mode 100644
index 0000000000..716a96fde3
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/resources/persistence-h2.properties
@@ -0,0 +1,13 @@
+# jdbc.X
+jdbc.driverClassName=org.h2.Driver
+jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
+jdbc.user=sa
+jdbc.pass=
+
+# hibernate.X
+hibernate.dialect=org.hibernate.dialect.H2Dialect
+hibernate.show_sql=true
+hibernate.hbm2ddl.auto=create-drop
+hibernate.cache.use_second_level_cache=true
+hibernate.cache.use_query_cache=true
+hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/persistence-mysql.properties b/persistence-modules/spring-persistence-simple/src/main/resources/persistence-mysql.properties
new file mode 100644
index 0000000000..b3cfd31f46
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/resources/persistence-mysql.properties
@@ -0,0 +1,13 @@
+# jdbc.X
+jdbc.driverClassName=com.mysql.cj.jdbc.Driver
+jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate5_01?createDatabaseIfNotExist=true
+jdbc.eventGeneratedId=tutorialuser
+jdbc.pass=tutorialmy5ql
+
+# hibernate.X
+hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
+hibernate.show_sql=false
+hibernate.hbm2ddl.auto=create-drop
+
+# envers.X
+envers.audit_table_suffix=_audit_log
diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/persistence.xml b/persistence-modules/spring-persistence-simple/src/main/resources/persistence.xml
new file mode 100644
index 0000000000..6304fa0a65
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/resources/persistence.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${hibernate.hbm2ddl.auto}
+ ${hibernate.dialect}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/springDataPersistenceConfig.xml b/persistence-modules/spring-persistence-simple/src/main/resources/springDataPersistenceConfig.xml
new file mode 100644
index 0000000000..d6d0ec6e47
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/resources/springDataPersistenceConfig.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/main/resources/stored_procedure.sql b/persistence-modules/spring-persistence-simple/src/main/resources/stored_procedure.sql
new file mode 100644
index 0000000000..9cedb75c37
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/main/resources/stored_procedure.sql
@@ -0,0 +1,20 @@
+DELIMITER //
+ CREATE PROCEDURE GetFoosByName(IN fooName VARCHAR(255))
+ LANGUAGE SQL
+ DETERMINISTIC
+ SQL SECURITY DEFINER
+ BEGIN
+ SELECT * FROM foo WHERE name = fooName;
+ END //
+DELIMITER ;
+
+
+DELIMITER //
+ CREATE PROCEDURE GetAllFoos()
+ LANGUAGE SQL
+ DETERMINISTIC
+ SQL SECURITY DEFINER
+ BEGIN
+ SELECT * FROM foo;
+ END //
+DELIMITER ;
\ No newline at end of file
diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateBootstrapIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateBootstrapIntegrationTest.java
new file mode 100644
index 0000000000..c41423643a
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateBootstrapIntegrationTest.java
@@ -0,0 +1,185 @@
+package com.baeldung.hibernate.bootstrap;
+
+import com.baeldung.hibernate.bootstrap.model.TestEntity;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.Commit;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+import org.springframework.test.context.transaction.TestTransaction;
+import org.springframework.transaction.annotation.Transactional;
+
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertTrue;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { HibernateConf.class })
+@Transactional
+public class HibernateBootstrapIntegrationTest {
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ @Test
+ public void whenBootstrapHibernateSession_thenNoException() {
+
+ Session session = sessionFactory.getCurrentSession();
+
+ TestEntity newEntity = new TestEntity();
+ newEntity.setId(1);
+ session.save(newEntity);
+
+ TestEntity searchEntity = session.find(TestEntity.class, 1);
+
+ Assert.assertNotNull(searchEntity);
+ }
+
+ @Test
+ public void whenProgrammaticTransactionCommit_thenEntityIsInDatabase() {
+ assertTrue(TestTransaction.isActive());
+
+ //Save an entity and commit.
+ Session session = sessionFactory.getCurrentSession();
+
+ TestEntity newEntity = new TestEntity();
+ newEntity.setId(1);
+ session.save(newEntity);
+
+ TestEntity searchEntity = session.find(TestEntity.class, 1);
+
+ Assert.assertNotNull(searchEntity);
+ assertTrue(TestTransaction.isFlaggedForRollback());
+
+ TestTransaction.flagForCommit();
+ TestTransaction.end();
+
+ assertFalse(TestTransaction.isFlaggedForRollback());
+ assertFalse(TestTransaction.isActive());
+
+ //Check that the entity is still there in a new transaction,
+ //then delete it, but don't commit.
+ TestTransaction.start();
+
+ assertTrue(TestTransaction.isFlaggedForRollback());
+ assertTrue(TestTransaction.isActive());
+
+ session = sessionFactory.getCurrentSession();
+ searchEntity = session.find(TestEntity.class, 1);
+
+ Assert.assertNotNull(searchEntity);
+
+ session.delete(searchEntity);
+ session.flush();
+
+ TestTransaction.end();
+
+ assertFalse(TestTransaction.isActive());
+
+ //Check that the entity is still there in a new transaction,
+ //then delete it and commit.
+ TestTransaction.start();
+
+ session = sessionFactory.getCurrentSession();
+ searchEntity = session.find(TestEntity.class, 1);
+
+ Assert.assertNotNull(searchEntity);
+
+ session.delete(searchEntity);
+ session.flush();
+
+ assertTrue(TestTransaction.isActive());
+
+ TestTransaction.flagForCommit();
+ TestTransaction.end();
+
+ assertFalse(TestTransaction.isActive());
+
+ //Check that the entity is no longer there in a new transaction.
+ TestTransaction.start();
+
+ assertTrue(TestTransaction.isActive());
+
+ session = sessionFactory.getCurrentSession();
+ searchEntity = session.find(TestEntity.class, 1);
+
+ Assert.assertNull(searchEntity);
+ }
+
+ @Test
+ @Commit
+ public void givenTransactionCommitDefault_whenProgrammaticTransactionCommit_thenEntityIsInDatabase() {
+ assertTrue(TestTransaction.isActive());
+
+ //Save an entity and commit.
+ Session session = sessionFactory.getCurrentSession();
+
+ TestEntity newEntity = new TestEntity();
+ newEntity.setId(1);
+ session.save(newEntity);
+
+ TestEntity searchEntity = session.find(TestEntity.class, 1);
+
+ Assert.assertNotNull(searchEntity);
+ assertFalse(TestTransaction.isFlaggedForRollback());
+
+ TestTransaction.end();
+
+ assertFalse(TestTransaction.isFlaggedForRollback());
+ assertFalse(TestTransaction.isActive());
+
+ //Check that the entity is still there in a new transaction,
+ //then delete it, but don't commit.
+ TestTransaction.start();
+
+ assertFalse(TestTransaction.isFlaggedForRollback());
+ assertTrue(TestTransaction.isActive());
+
+ session = sessionFactory.getCurrentSession();
+ searchEntity = session.find(TestEntity.class, 1);
+
+ Assert.assertNotNull(searchEntity);
+
+ session.delete(searchEntity);
+ session.flush();
+
+ TestTransaction.flagForRollback();
+ TestTransaction.end();
+
+ assertFalse(TestTransaction.isActive());
+
+ //Check that the entity is still there in a new transaction,
+ //then delete it and commit.
+ TestTransaction.start();
+
+ session = sessionFactory.getCurrentSession();
+ searchEntity = session.find(TestEntity.class, 1);
+
+ Assert.assertNotNull(searchEntity);
+
+ session.delete(searchEntity);
+ session.flush();
+
+ assertTrue(TestTransaction.isActive());
+
+ TestTransaction.end();
+
+ assertFalse(TestTransaction.isActive());
+
+ //Check that the entity is no longer there in a new transaction.
+ TestTransaction.start();
+
+ assertTrue(TestTransaction.isActive());
+
+ session = sessionFactory.getCurrentSession();
+ searchEntity = session.find(TestEntity.class, 1);
+
+ Assert.assertNull(searchEntity);
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateXMLBootstrapIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateXMLBootstrapIntegrationTest.java
new file mode 100644
index 0000000000..5b811ad576
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/hibernate/bootstrap/HibernateXMLBootstrapIntegrationTest.java
@@ -0,0 +1,36 @@
+package com.baeldung.hibernate.bootstrap;
+
+import com.baeldung.hibernate.bootstrap.model.TestEntity;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { HibernateXMLConf.class })
+@Transactional
+public class HibernateXMLBootstrapIntegrationTest {
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ @Test
+ public void whenBootstrapHibernateSession_thenNoException() {
+
+ Session session = sessionFactory.getCurrentSession();
+
+ TestEntity newEntity = new TestEntity();
+ newEntity.setId(1);
+ session.save(newEntity);
+
+ TestEntity searchEntity = session.find(TestEntity.class, 1);
+
+ Assert.assertNotNull(searchEntity);
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java
new file mode 100644
index 0000000000..76c34affb9
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooPaginationPersistenceIntegrationTest.java
@@ -0,0 +1,157 @@
+package org.baeldung.persistence.service;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.lessThan;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+
+import org.baeldung.config.PersistenceJPAConfig;
+import org.baeldung.persistence.model.Foo;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class)
+@DirtiesContext
+public class FooPaginationPersistenceIntegrationTest {
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ @Autowired
+ private FooService fooService;
+
+ @Before
+ public final void before() {
+ final int minimalNumberOfEntities = 25;
+ if (fooService.findAll().size() <= minimalNumberOfEntities) {
+ for (int i = 0; i < minimalNumberOfEntities; i++) {
+ fooService.create(new Foo(randomAlphabetic(6)));
+ }
+ }
+ }
+
+ // tests
+
+ @Test
+ public final void whenContextIsBootstrapped_thenNoExceptions() {
+ //
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void givenEntitiesExist_whenRetrievingFirstPage_thenCorrect() {
+ final int pageSize = 10;
+
+ final Query query = entityManager.createQuery("From Foo");
+ configurePagination(query, 1, pageSize);
+
+ // When
+ final List fooList = query.getResultList();
+
+ // Then
+ assertThat(fooList, hasSize(pageSize));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void givenEntitiesExist_whenRetrievingLastPage_thenCorrect() {
+ final int pageSize = 10;
+ final Query queryTotal = entityManager.createQuery("Select count(f.id) from Foo f");
+ final long countResult = (long) queryTotal.getSingleResult();
+
+ final Query query = entityManager.createQuery("Select f from Foo as f order by f.id");
+ final int lastPage = (int) ((countResult / pageSize) + 1);
+ configurePagination(query, lastPage, pageSize);
+ final List fooList = query.getResultList();
+
+ // Then
+ assertThat(fooList, hasSize(lessThan(pageSize + 1)));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void givenEntitiesExist_whenRetrievingPage_thenCorrect() {
+ final int pageSize = 10;
+
+ final Query queryIds = entityManager.createQuery("Select f.id from Foo f order by f.name");
+ final List fooIds = queryIds.getResultList();
+
+ final Query query = entityManager.createQuery("Select f from Foo as f where f.id in :ids");
+ query.setParameter("ids", fooIds.subList(0, pageSize));
+
+ final List fooList = query.getResultList();
+
+ // Then
+ assertThat(fooList, hasSize(pageSize));
+ }
+
+ @Test
+ public final void givenEntitiesExist_whenRetrievingPageViaCriteria_thenCorrect() {
+ final int pageSize = 10;
+ final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+ final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class);
+ final Root from = criteriaQuery.from(Foo.class);
+ final CriteriaQuery select = criteriaQuery.select(from);
+ final TypedQuery typedQuery = entityManager.createQuery(select);
+ typedQuery.setFirstResult(0);
+ typedQuery.setMaxResults(pageSize);
+ final List fooList = typedQuery.getResultList();
+
+ // Then
+ assertThat(fooList, hasSize(pageSize));
+ }
+
+ @Test
+ public final void givenEntitiesExist_whenRetrievingPageViaCriteria_thenNoExceptions() {
+ int pageNumber = 1;
+ final int pageSize = 10;
+ final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+
+ final CriteriaQuery countQuery = criteriaBuilder.createQuery(Long.class);
+ countQuery.select(criteriaBuilder.count(countQuery.from(Foo.class)));
+ final Long count = entityManager.createQuery(countQuery).getSingleResult();
+
+ final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class);
+ final Root from = criteriaQuery.from(Foo.class);
+ final CriteriaQuery select = criteriaQuery.select(from);
+
+ TypedQuery typedQuery;
+ while (pageNumber < count.intValue()) {
+ typedQuery = entityManager.createQuery(select);
+ typedQuery.setFirstResult(pageNumber - 1);
+ typedQuery.setMaxResults(pageSize);
+ System.out.println("Current page: " + typedQuery.getResultList());
+ pageNumber += pageSize;
+ }
+
+ }
+
+ // UTIL
+
+ final int determineLastPage(final int pageSize, final long countResult) {
+ return (int) (countResult / pageSize) + 1;
+ }
+
+ final void configurePagination(final Query query, final int pageNumber, final int pageSize) {
+ query.setFirstResult((pageNumber - 1) * pageSize);
+ query.setMaxResults(pageSize);
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java
new file mode 100644
index 0000000000..e1b53c8ded
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java
@@ -0,0 +1,69 @@
+package org.baeldung.persistence.service;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+
+import org.baeldung.config.PersistenceJPAConfig;
+import org.baeldung.persistence.model.Foo;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class)
+@DirtiesContext
+public class FooServicePersistenceIntegrationTest {
+
+ @Autowired
+ private FooService service;
+
+ // tests
+
+ @Test
+ public final void whenContextIsBootstrapped_thenNoExceptions() {
+ //
+ }
+
+ @Test
+ public final void whenEntityIsCreated_thenNoExceptions() {
+ service.create(new Foo(randomAlphabetic(6)));
+ }
+
+ @Test(expected = DataIntegrityViolationException.class)
+ public final void whenInvalidEntityIsCreated_thenDataException() {
+ service.create(new Foo(randomAlphabetic(2048)));
+ }
+
+ @Test(expected = DataIntegrityViolationException.class)
+ public final void whenEntityWithLongNameIsCreated_thenDataException() {
+ service.create(new Foo(randomAlphabetic(2048)));
+ }
+
+ @Test(expected = InvalidDataAccessApiUsageException.class)
+ public final void whenSameEntityIsCreatedTwice_thenDataException() {
+ final Foo entity = new Foo(randomAlphabetic(8));
+ service.create(entity);
+ service.create(entity);
+ }
+
+ @Test(expected = DataAccessException.class)
+ public final void temp_whenInvalidEntityIsCreated_thenDataException() {
+ service.create(new Foo(randomAlphabetic(2048)));
+ }
+
+ @Test
+ public final void whenEntityIsCreated_thenFound() {
+ final Foo fooEntity = new Foo("abc");
+ service.create(fooEntity);
+ final Foo found = service.findOne(fooEntity.getId());
+ Assert.assertNotNull(found);
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingIntegrationTest.java
new file mode 100644
index 0000000000..40249b4b30
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingIntegrationTest.java
@@ -0,0 +1,118 @@
+package org.baeldung.persistence.service;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+
+import org.baeldung.config.PersistenceJPAConfig;
+import org.baeldung.persistence.model.Bar;
+import org.baeldung.persistence.model.Foo;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class)
+@DirtiesContext
+@SuppressWarnings("unchecked")
+public class FooServiceSortingIntegrationTest {
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ // tests
+
+ @Test
+ public final void whenSortingByOneAttributeDefaultOrder_thenPrintSortedResult() {
+ final String jql = "Select f from Foo as f order by f.id";
+ final Query sortQuery = entityManager.createQuery(jql);
+ final List fooList = sortQuery.getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenSortingByOneAttributeSetOrder_thenSortedPrintResult() {
+ final String jql = "Select f from Foo as f order by f.id desc";
+ final Query sortQuery = entityManager.createQuery(jql);
+ final List fooList = sortQuery.getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenSortingByTwoAttributes_thenPrintSortedResult() {
+ final String jql = "Select f from Foo as f order by f.name asc, f.id desc";
+ final Query sortQuery = entityManager.createQuery(jql);
+ final List fooList = sortQuery.getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenSortingFooByBar_thenBarsSorted() {
+ final String jql = "Select f from Foo as f order by f.name, f.bar.id";
+ final Query barJoinQuery = entityManager.createQuery(jql);
+ final List fooList = barJoinQuery.getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName());
+ if (foo.getBar() != null) {
+ System.out.print("-------BarId:" + foo.getBar().getId());
+ }
+ }
+ }
+
+ @Test
+ public final void whenSortinfBar_thenPrintBarsSortedWithFoos() {
+ final String jql = "Select b from Bar as b order by b.id";
+ final Query barQuery = entityManager.createQuery(jql);
+ final List barList = barQuery.getResultList();
+ for (final Bar bar : barList) {
+ System.out.println("Bar Id:" + bar.getId());
+ for (final Foo foo : bar.getFooList()) {
+ System.out.println("FooName:" + foo.getName());
+ }
+ }
+ }
+
+ @Test
+ public final void whenSortingFooWithCriteria_thenPrintSortedFoos() {
+ final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+ final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class);
+ final Root from = criteriaQuery.from(Foo.class);
+ final CriteriaQuery select = criteriaQuery.select(from);
+ criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name")));
+ final TypedQuery typedQuery = entityManager.createQuery(select);
+ final List fooList = typedQuery.getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName() + "--------Id:" + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenSortingFooWithCriteriaAndMultipleAttributes_thenPrintSortedFoos() {
+ final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
+ final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Foo.class);
+ final Root from = criteriaQuery.from(Foo.class);
+ final CriteriaQuery select = criteriaQuery.select(from);
+ criteriaQuery.orderBy(criteriaBuilder.asc(from.get("name")), criteriaBuilder.desc(from.get("id")));
+ final TypedQuery typedQuery = entityManager.createQuery(select);
+ final List fooList = typedQuery.getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName() + "-------Id:" + foo.getId());
+ }
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java
new file mode 100644
index 0000000000..c530003ac1
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooServiceSortingWitNullsManualIntegrationTest.java
@@ -0,0 +1,64 @@
+package org.baeldung.persistence.service;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+import static org.junit.Assert.assertNull;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+
+import org.baeldung.config.PersistenceJPAConfig;
+import org.baeldung.persistence.model.Foo;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceJPAConfig.class }, loader = AnnotationConfigContextLoader.class)
+@DirtiesContext
+public class FooServiceSortingWitNullsManualIntegrationTest {
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ @Autowired
+ private FooService service;
+
+ // tests
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void whenSortingByStringNullLast_thenLastNull() {
+ service.create(new Foo());
+ service.create(new Foo(randomAlphabetic(6)));
+
+ final String jql = "Select f from Foo as f order by f.name desc NULLS LAST";
+ final Query sortQuery = entityManager.createQuery(jql);
+ final List fooList = sortQuery.getResultList();
+ assertNull(fooList.get(fooList.toArray().length - 1).getName());
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName());
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void whenSortingByStringNullFirst_thenFirstNull() {
+ service.create(new Foo());
+
+ final String jql = "Select f from Foo as f order by f.name desc NULLS FIRST";
+ final Query sortQuery = entityManager.createQuery(jql);
+ final List fooList = sortQuery.getResultList();
+ assertNull(fooList.get(0).getName());
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName());
+ }
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooStoredProceduresLiveTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooStoredProceduresLiveTest.java
new file mode 100644
index 0000000000..ded32e362e
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/persistence/service/FooStoredProceduresLiveTest.java
@@ -0,0 +1,123 @@
+package org.baeldung.persistence.service;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import org.baeldung.config.PersistenceConfig;
+import org.baeldung.persistence.model.Foo;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.exception.SQLGrammarException;
+import org.hibernate.query.NativeQuery;
+import org.hibernate.query.Query;
+import org.junit.After;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class FooStoredProceduresLiveTest {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(FooStoredProceduresLiveTest.class);
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ @Autowired
+ private FooService fooService;
+
+ private Session session;
+
+ @Before
+ public final void before() {
+ session = sessionFactory.openSession();
+ Assume.assumeTrue(getAllFoosExists());
+ Assume.assumeTrue(getFoosByNameExists());
+ }
+
+ private boolean getFoosByNameExists() {
+ try {
+ @SuppressWarnings("unchecked")
+ NativeQuery sqlQuery = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class);
+ sqlQuery.list();
+ return true;
+ } catch (SQLGrammarException e) {
+ LOGGER.error("WARNING : GetFoosByName() Procedure is may be missing ", e);
+ return false;
+ }
+ }
+
+ private boolean getAllFoosExists() {
+ try {
+ @SuppressWarnings("unchecked")
+ NativeQuery sqlQuery = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class);
+ sqlQuery.list();
+ return true;
+ } catch (SQLGrammarException e) {
+ LOGGER.error("WARNING : GetAllFoos() Procedure is may be missing ", e);
+ return false;
+ }
+ }
+
+ @After
+ public final void after() {
+ session.close();
+ }
+
+ @Test
+ public final void getAllFoosUsingStoredProcedures() {
+
+ fooService.create(new Foo(randomAlphabetic(6)));
+
+ // Stored procedure getAllFoos using createSQLQuery
+ @SuppressWarnings("unchecked")
+ NativeQuery sqlQuery = session.createSQLQuery("CALL GetAllFoos()").addEntity(Foo.class);
+ List allFoos = sqlQuery.list();
+ for (Foo foo : allFoos) {
+ LOGGER.info("getAllFoos() SQL Query result : {}", foo.getName());
+ }
+ assertEquals(allFoos.size(), fooService.findAll().size());
+
+ // Stored procedure getAllFoos using a Named Query
+ @SuppressWarnings("unchecked")
+ Query namedQuery = session.getNamedQuery("callGetAllFoos");
+ List allFoos2 = namedQuery.list();
+ for (Foo foo : allFoos2) {
+ LOGGER.info("getAllFoos() NamedQuery result : {}", foo.getName());
+ }
+ assertEquals(allFoos2.size(), fooService.findAll().size());
+ }
+
+ @Test
+ public final void getFoosByNameUsingStoredProcedures() {
+
+ fooService.create(new Foo("NewFooName"));
+
+ // Stored procedure getFoosByName using createSQLQuery()
+ @SuppressWarnings("unchecked")
+ Query sqlQuery = session.createSQLQuery("CALL GetFoosByName(:fooName)").addEntity(Foo.class).setParameter("fooName", "NewFooName");
+ List allFoosByName = sqlQuery.list();
+ for (Foo foo : allFoosByName) {
+ LOGGER.info("getFoosByName() using SQL Query : found => {}", foo.toString());
+ }
+
+ // Stored procedure getFoosByName using getNamedQuery()
+ @SuppressWarnings("unchecked")
+ Query namedQuery = session.getNamedQuery("callGetFoosByName").setParameter("fooName", "NewFooName");
+ List allFoosByName2 = namedQuery.list();
+ for (Foo foo : allFoosByName2) {
+ LOGGER.info("getFoosByName() using Native Query : found => {}", foo.toString());
+ }
+
+ }
+}
diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCommon.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCommon.java
new file mode 100644
index 0000000000..8f119a04e0
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryCommon.java
@@ -0,0 +1,561 @@
+package org.baeldung.spring.data.persistence.dao.user;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.baeldung.spring.data.persistence.config.PersistenceConfig;
+import org.baeldung.spring.data.persistence.model.User;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.JpaSort;
+import org.springframework.data.mapping.PropertyReferenceException;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+import org.springframework.transaction.annotation.Transactional;
+
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+@DirtiesContext
+public class UserRepositoryCommon {
+
+ final String USER_EMAIL = "email@example.com";
+ final String USER_EMAIL2 = "email2@example.com";
+ final String USER_EMAIL3 = "email3@example.com";
+ final String USER_EMAIL4 = "email4@example.com";
+ final Integer INACTIVE_STATUS = 0;
+ final Integer ACTIVE_STATUS = 1;
+ final String USER_EMAIL5 = "email5@example.com";
+ final String USER_EMAIL6 = "email6@example.com";
+ final String USER_NAME_ADAM = "Adam";
+ final String USER_NAME_PETER = "Peter";
+
+ @Autowired
+ protected UserRepository userRepository;
+ @Autowired
+ private EntityManager entityManager;
+
+ @Test
+ @Transactional
+ public void givenUsersWithSameNameInDB_WhenFindAllByName_ThenReturnStreamOfUsers() {
+ User user1 = new User();
+ user1.setName(USER_NAME_ADAM);
+ user1.setEmail(USER_EMAIL);
+ userRepository.save(user1);
+
+ User user2 = new User();
+ user2.setName(USER_NAME_ADAM);
+ user2.setEmail(USER_EMAIL2);
+ userRepository.save(user2);
+
+ User user3 = new User();
+ user3.setName(USER_NAME_ADAM);
+ user3.setEmail(USER_EMAIL3);
+ userRepository.save(user3);
+
+ User user4 = new User();
+ user4.setName("SAMPLE");
+ user4.setEmail(USER_EMAIL4);
+ userRepository.save(user4);
+
+ try (Stream foundUsersStream = userRepository.findAllByName(USER_NAME_ADAM)) {
+ assertThat(foundUsersStream.count()).isEqualTo(3l);
+ }
+ }
+
+ @Test
+ public void givenUsersInDB_WhenFindAllWithQueryAnnotation_ThenReturnCollectionWithActiveUsers() {
+ User user1 = new User();
+ user1.setName(USER_NAME_ADAM);
+ user1.setEmail(USER_EMAIL);
+ user1.setStatus(ACTIVE_STATUS);
+ userRepository.save(user1);
+
+ User user2 = new User();
+ user2.setName(USER_NAME_ADAM);
+ user2.setEmail(USER_EMAIL2);
+ user2.setStatus(ACTIVE_STATUS);
+ userRepository.save(user2);
+
+ User user3 = new User();
+ user3.setName(USER_NAME_ADAM);
+ user3.setEmail(USER_EMAIL3);
+ user3.setStatus(INACTIVE_STATUS);
+ userRepository.save(user3);
+
+ Collection allActiveUsers = userRepository.findAllActiveUsers();
+
+ assertThat(allActiveUsers.size()).isEqualTo(2);
+ }
+
+ @Test
+ public void givenUsersInDB_WhenFindAllWithQueryAnnotationNative_ThenReturnCollectionWithActiveUsers() {
+ User user1 = new User();
+ user1.setName(USER_NAME_ADAM);
+ user1.setEmail(USER_EMAIL);
+ user1.setStatus(ACTIVE_STATUS);
+ userRepository.save(user1);
+
+ User user2 = new User();
+ user2.setName(USER_NAME_ADAM);
+ user2.setEmail(USER_EMAIL2);
+ user2.setStatus(ACTIVE_STATUS);
+ userRepository.save(user2);
+
+ User user3 = new User();
+ user3.setName(USER_NAME_ADAM);
+ user3.setEmail(USER_EMAIL3);
+ user3.setStatus(INACTIVE_STATUS);
+ userRepository.save(user3);
+
+ Collection allActiveUsers = userRepository.findAllActiveUsersNative();
+
+ assertThat(allActiveUsers.size()).isEqualTo(2);
+ }
+
+ @Test
+ public void givenUserInDB_WhenFindUserByStatusWithQueryAnnotation_ThenReturnActiveUser() {
+ User user = new User();
+ user.setName(USER_NAME_ADAM);
+ user.setEmail(USER_EMAIL);
+ user.setStatus(ACTIVE_STATUS);
+ userRepository.save(user);
+
+ User userByStatus = userRepository.findUserByStatus(ACTIVE_STATUS);
+
+ assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM);
+ }
+
+ @Test
+ public void givenUserInDB_WhenFindUserByStatusWithQueryAnnotationNative_ThenReturnActiveUser() {
+ User user = new User();
+ user.setName(USER_NAME_ADAM);
+ user.setEmail(USER_EMAIL);
+ user.setStatus(ACTIVE_STATUS);
+ userRepository.save(user);
+
+ User userByStatus = userRepository.findUserByStatusNative(ACTIVE_STATUS);
+
+ assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM);
+ }
+
+ @Test
+ public void givenUsersInDB_WhenFindUserByStatusAndNameWithQueryAnnotationIndexedParams_ThenReturnOneUser() {
+ User user = new User();
+ user.setName(USER_NAME_ADAM);
+ user.setEmail(USER_EMAIL);
+ user.setStatus(ACTIVE_STATUS);
+ userRepository.save(user);
+
+ User user2 = new User();
+ user2.setName(USER_NAME_PETER);
+ user2.setEmail(USER_EMAIL2);
+ user2.setStatus(ACTIVE_STATUS);
+ userRepository.save(user2);
+
+ User userByStatus = userRepository.findUserByStatusAndName(ACTIVE_STATUS, USER_NAME_ADAM);
+
+ assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM);
+ }
+
+ @Test
+ public void givenUsersInDB_WhenFindUserByStatusAndNameWithQueryAnnotationNamedParams_ThenReturnOneUser() {
+ User user = new User();
+ user.setName(USER_NAME_ADAM);
+ user.setEmail(USER_EMAIL);
+ user.setStatus(ACTIVE_STATUS);
+ userRepository.save(user);
+
+ User user2 = new User();
+ user2.setName(USER_NAME_PETER);
+ user2.setEmail(USER_EMAIL2);
+ user2.setStatus(ACTIVE_STATUS);
+ userRepository.save(user2);
+
+ User userByStatus = userRepository.findUserByStatusAndNameNamedParams(ACTIVE_STATUS, USER_NAME_ADAM);
+
+ assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM);
+ }
+
+ @Test
+ public void givenUsersInDB_WhenFindUserByStatusAndNameWithQueryAnnotationNativeNamedParams_ThenReturnOneUser() {
+ User user = new User();
+ user.setName(USER_NAME_ADAM);
+ user.setEmail(USER_EMAIL);
+ user.setStatus(ACTIVE_STATUS);
+ userRepository.save(user);
+
+ User user2 = new User();
+ user2.setName(USER_NAME_PETER);
+ user2.setEmail(USER_EMAIL2);
+ user2.setStatus(ACTIVE_STATUS);
+ userRepository.save(user2);
+
+ User userByStatus = userRepository.findUserByStatusAndNameNamedParamsNative(ACTIVE_STATUS, USER_NAME_ADAM);
+
+ assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM);
+ }
+
+ @Test
+ public void givenUsersInDB_WhenFindUserByStatusAndNameWithQueryAnnotationNamedParamsCustomNames_ThenReturnOneUser() {
+ User user = new User();
+ user.setName(USER_NAME_ADAM);
+ user.setEmail(USER_EMAIL);
+ user.setStatus(ACTIVE_STATUS);
+ userRepository.save(user);
+
+ User user2 = new User();
+ user2.setName(USER_NAME_PETER);
+ user2.setEmail(USER_EMAIL2);
+ user2.setStatus(ACTIVE_STATUS);
+ userRepository.save(user2);
+
+ User userByStatus = userRepository.findUserByUserStatusAndUserName(ACTIVE_STATUS, USER_NAME_ADAM);
+
+ assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM);
+ }
+
+ @Test
+ public void givenUsersInDB_WhenFindUserByNameLikeWithQueryAnnotationIndexedParams_ThenReturnUser() {
+ User user = new User();
+ user.setName(USER_NAME_ADAM);
+ user.setEmail(USER_EMAIL);
+ user.setStatus(ACTIVE_STATUS);
+ userRepository.save(user);
+
+ User userByStatus = userRepository.findUserByNameLike("Ad");
+
+ assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM);
+ }
+
+ @Test
+ public void givenUsersInDB_WhenFindUserByNameLikeWithQueryAnnotationNamedParams_ThenReturnUser() {
+ User user = new User();
+ user.setName(USER_NAME_ADAM);
+ user.setEmail(USER_EMAIL);
+ user.setStatus(ACTIVE_STATUS);
+ userRepository.save(user);
+
+ User userByStatus = userRepository.findUserByNameLikeNamedParam("Ad");
+
+ assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM);
+ }
+
+ @Test
+ public void givenUsersInDB_WhenFindUserByNameLikeWithQueryAnnotationNative_ThenReturnUser() {
+ User user = new User();
+ user.setName(USER_NAME_ADAM);
+ user.setEmail(USER_EMAIL);
+ user.setStatus(ACTIVE_STATUS);
+ userRepository.save(user);
+
+ User userByStatus = userRepository.findUserByNameLikeNative("Ad");
+
+ assertThat(userByStatus.getName()).isEqualTo(USER_NAME_ADAM);
+ }
+
+ @Test
+ public void givenUsersInDB_WhenFindAllWithSortByName_ThenReturnUsersSorted() {
+ userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS));
+ userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS));
+
+ List usersSortByName = userRepository.findAll(new Sort(Sort.Direction.ASC, "name"));
+
+ assertThat(usersSortByName.get(0)
+ .getName()).isEqualTo(USER_NAME_ADAM);
+ }
+
+ @Test(expected = PropertyReferenceException.class)
+ public void givenUsersInDB_WhenFindAllSortWithFunction_ThenThrowException() {
+ userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS));
+ userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS));
+
+ userRepository.findAll(new Sort(Sort.Direction.ASC, "name"));
+
+ List usersSortByNameLength = userRepository.findAll(Sort.by("LENGTH(name)"));
+
+ assertThat(usersSortByNameLength.get(0)
+ .getName()).isEqualTo(USER_NAME_ADAM);
+ }
+
+ @Test
+ public void givenUsersInDB_WhenFindAllSortWithFunctionQueryAnnotationJPQL_ThenReturnUsersSorted() {
+ userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS));
+ userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS));
+
+ userRepository.findAllUsers(Sort.by("name"));
+
+ List usersSortByNameLength = userRepository.findAllUsers(JpaSort.unsafe("LENGTH(name)"));
+
+ assertThat(usersSortByNameLength.get(0)
+ .getName()).isEqualTo(USER_NAME_ADAM);
+ }
+
+ @Test
+ public void givenUsersInDB_WhenFindAllWithPageRequestQueryAnnotationJPQL_ThenReturnPageOfUsers() {
+ userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS));
+ userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE1", LocalDate.now(), USER_EMAIL4, INACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE2", LocalDate.now(), USER_EMAIL5, INACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE3", LocalDate.now(), USER_EMAIL6, INACTIVE_STATUS));
+
+ Page usersPage = userRepository.findAllUsersWithPagination(PageRequest.of(1, 3));
+
+ assertThat(usersPage.getContent()
+ .get(0)
+ .getName()).isEqualTo("SAMPLE1");
+ }
+
+ @Test
+ public void givenUsersInDB_WhenFindAllWithPageRequestQueryAnnotationNative_ThenReturnPageOfUsers() {
+ userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS));
+ userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE1", LocalDate.now(), USER_EMAIL4, INACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE2", LocalDate.now(), USER_EMAIL5, INACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE3", LocalDate.now(), USER_EMAIL6, INACTIVE_STATUS));
+
+ Page usersSortByNameLength = userRepository.findAllUsersWithPaginationNative(PageRequest.of(1, 3));
+
+ assertThat(usersSortByNameLength.getContent()
+ .get(0)
+ .getName()).isEqualTo(USER_NAME_PETER);
+ }
+
+ @Test
+ @Transactional
+ public void givenUsersInDB_WhenUpdateStatusForNameModifyingQueryAnnotationJPQL_ThenModifyMatchingUsers() {
+ userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL, ACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE1", LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, ACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE3", LocalDate.now(), USER_EMAIL4, ACTIVE_STATUS));
+
+ int updatedUsersSize = userRepository.updateUserSetStatusForName(INACTIVE_STATUS, "SAMPLE");
+
+ assertThat(updatedUsersSize).isEqualTo(2);
+ }
+
+ @Test
+ public void givenUsersInDB_WhenFindByEmailsWithDynamicQuery_ThenReturnCollection() {
+
+ User user1 = new User();
+ user1.setEmail(USER_EMAIL);
+ userRepository.save(user1);
+
+ User user2 = new User();
+ user2.setEmail(USER_EMAIL2);
+ userRepository.save(user2);
+
+ User user3 = new User();
+ user3.setEmail(USER_EMAIL3);
+ userRepository.save(user3);
+
+ Set emails = new HashSet<>();
+ emails.add(USER_EMAIL2);
+ emails.add(USER_EMAIL3);
+
+ Collection usersWithEmails = userRepository.findUserByEmails(emails);
+
+ assertThat(usersWithEmails.size()).isEqualTo(2);
+ }
+
+ @Test
+ public void givenUsersInDBWhenFindByNameListReturnCollection() {
+
+ User user1 = new User();
+ user1.setName(USER_NAME_ADAM);
+ user1.setEmail(USER_EMAIL);
+ userRepository.save(user1);
+
+ User user2 = new User();
+ user2.setName(USER_NAME_PETER);
+ user2.setEmail(USER_EMAIL2);
+ userRepository.save(user2);
+
+ List names = Arrays.asList(USER_NAME_ADAM, USER_NAME_PETER);
+
+ List usersWithNames = userRepository.findUserByNameList(names);
+
+ assertThat(usersWithNames.size()).isEqualTo(2);
+ }
+
+
+ @Test
+ @Transactional
+ public void whenInsertedWithQuery_ThenUserIsPersisted() {
+ userRepository.insertUser(USER_NAME_ADAM, 1, USER_EMAIL, ACTIVE_STATUS, true);
+ userRepository.insertUser(USER_NAME_PETER, 1, USER_EMAIL2, ACTIVE_STATUS, true);
+
+ User userAdam = userRepository.findUserByNameLike(USER_NAME_ADAM);
+ User userPeter = userRepository.findUserByNameLike(USER_NAME_PETER);
+
+ assertThat(userAdam).isNotNull();
+ assertThat(userAdam.getEmail()).isEqualTo(USER_EMAIL);
+ assertThat(userPeter).isNotNull();
+ assertThat(userPeter.getEmail()).isEqualTo(USER_EMAIL2);
+ }
+
+
+ @Test
+ @Transactional
+ public void givenTwoUsers_whenFindByNameUsr01_ThenUserUsr01() {
+ User usr01 = new User("usr01", LocalDate.now(), "usr01@baeldung.com", 1);
+ User usr02 = new User("usr02", LocalDate.now(), "usr02@baeldung.com", 1);
+
+ userRepository.save(usr01);
+ userRepository.save(usr02);
+
+ try (Stream users = userRepository.findAllByName("usr01")) {
+ assertTrue(users.allMatch(usr -> usr.equals(usr01)));
+ }
+ }
+
+ @Test
+ @Transactional
+ public void givenTwoUsers_whenFindByNameUsr00_ThenNoUsers() {
+ User usr01 = new User("usr01", LocalDate.now(), "usr01@baeldung.com", 1);
+ User usr02 = new User("usr02", LocalDate.now(), "usr02@baeldung.com", 1);
+
+ userRepository.save(usr01);
+ userRepository.save(usr02);
+
+ try (Stream users = userRepository.findAllByName("usr00")) {
+ assertEquals(0, users.count());
+ }
+ }
+
+ @Test
+ public void givenTwoUsers_whenFindUsersWithGmailAddress_ThenUserUsr02() {
+ User usr01 = new User("usr01", LocalDate.now(), "usr01@baeldung.com", 1);
+ User usr02 = new User("usr02", LocalDate.now(), "usr02@gmail.com", 1);
+
+ userRepository.save(usr01);
+ userRepository.save(usr02);
+
+ List users = userRepository.findUsersWithGmailAddress();
+ assertEquals(1, users.size());
+ assertEquals(usr02, users.get(0));
+ }
+
+ @Test
+ @Transactional
+ public void givenTwoUsers_whenDeleteAllByCreationDateAfter_ThenOneUserRemains() {
+ User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1);
+ User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.com", 1);
+
+ userRepository.save(usr01);
+ userRepository.save(usr02);
+
+ userRepository.deleteAllByCreationDateAfter(LocalDate.of(2018, 5, 1));
+
+ List users = userRepository.findAll();
+
+ assertEquals(1, users.size());
+ assertEquals(usr01, users.get(0));
+ }
+
+ @Test
+ public void givenTwoUsers_whenFindAllUsersByPredicates_ThenUserUsr01() {
+ User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1);
+ User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.org", 1);
+
+ userRepository.save(usr01);
+ userRepository.save(usr02);
+
+ List> predicates = new ArrayList<>();
+ predicates.add(usr -> usr.getCreationDate().isAfter(LocalDate.of(2017, 12, 31)));
+ predicates.add(usr -> usr.getEmail().endsWith(".com"));
+
+ List users = userRepository.findAllUsersByPredicates(predicates);
+
+ assertEquals(1, users.size());
+ assertEquals(usr01, users.get(0));
+ }
+
+ @Test
+ @Transactional
+ public void givenTwoUsers_whenDeactivateUsersNotLoggedInSince_ThenUserUsr02Deactivated() {
+ User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1);
+ usr01.setLastLoginDate(LocalDate.now());
+ User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.org", 1);
+ usr02.setLastLoginDate(LocalDate.of(2018, 7, 20));
+
+ userRepository.save(usr01);
+ userRepository.save(usr02);
+
+ userRepository.deactivateUsersNotLoggedInSince(LocalDate.of(2018, 8, 1));
+
+ List users = userRepository.findAllUsers(Sort.by(Sort.Order.asc("name")));
+ assertTrue(users.get(0).isActive());
+ assertFalse(users.get(1).isActive());
+ }
+
+ @Test
+ @Transactional
+ public void givenTwoUsers_whenDeleteDeactivatedUsers_ThenUserUsr02Deleted() {
+ User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1);
+ usr01.setLastLoginDate(LocalDate.now());
+ User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.com", 0);
+ usr02.setLastLoginDate(LocalDate.of(2018, 7, 20));
+ usr02.setActive(false);
+
+ userRepository.save(usr01);
+ userRepository.save(usr02);
+
+ int deletedUsersCount = userRepository.deleteDeactivatedUsers();
+
+ List users = userRepository.findAll();
+ assertEquals(1, users.size());
+ assertEquals(usr01, users.get(0));
+ assertEquals(1, deletedUsersCount);
+ }
+
+ @Test
+ @Transactional
+ public void givenTwoUsers_whenAddDeletedColumn_ThenUsersHaveDeletedColumn() {
+ User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1);
+ usr01.setLastLoginDate(LocalDate.now());
+ User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.org", 1);
+ usr02.setLastLoginDate(LocalDate.of(2018, 7, 20));
+ usr02.setActive(false);
+
+ userRepository.save(usr01);
+ userRepository.save(usr02);
+
+ userRepository.addDeletedColumn();
+
+ Query nativeQuery = entityManager.createNativeQuery("select deleted from USERS where NAME = 'usr01'");
+ assertEquals(0, nativeQuery.getResultList().get(0));
+ }
+
+ @After
+ public void cleanUp() {
+ userRepository.deleteAll();
+ }
+}
diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryIntegrationTest.java
new file mode 100644
index 0000000000..b9b644f7e0
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/dao/user/UserRepositoryIntegrationTest.java
@@ -0,0 +1,38 @@
+package org.baeldung.spring.data.persistence.dao.user;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.time.LocalDate;
+
+import org.baeldung.spring.data.persistence.config.PersistenceConfig;
+import org.baeldung.spring.data.persistence.model.User;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * Created by adam.
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+@DirtiesContext
+public class UserRepositoryIntegrationTest extends UserRepositoryCommon {
+
+ @Test
+ @Transactional
+ public void givenUsersInDBWhenUpdateStatusForNameModifyingQueryAnnotationNativeThenModifyMatchingUsers() {
+ userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL, ACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE1", LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, ACTIVE_STATUS));
+ userRepository.save(new User("SAMPLE3", LocalDate.now(), USER_EMAIL4, ACTIVE_STATUS));
+ userRepository.flush();
+
+ int updatedUsersSize = userRepository.updateUserSetStatusForNameNative(INACTIVE_STATUS, "SAMPLE");
+
+ assertThat(updatedUsersSize).isEqualTo(2);
+ }
+}
diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/service/AbstractServicePersistenceIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/service/AbstractServicePersistenceIntegrationTest.java
new file mode 100644
index 0000000000..acc73dfaf8
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/service/AbstractServicePersistenceIntegrationTest.java
@@ -0,0 +1,256 @@
+package org.baeldung.spring.data.persistence.service;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.baeldung.spring.data.persistence.model.Foo;
+import org.baeldung.util.IDUtil;
+import org.hamcrest.Matchers;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.springframework.dao.DataAccessException;
+
+import com.baeldung.persistence.dao.common.IOperations;
+
+public abstract class AbstractServicePersistenceIntegrationTest {
+
+ // tests
+
+ // find - one
+
+ @Test
+ /**/public final void givenResourceDoesNotExist_whenResourceIsRetrieved_thenNoResourceIsReceived() {
+ // When
+ final Foo createdResource = getApi().findOne(IDUtil.randomPositiveLong());
+
+ // Then
+ assertNull(createdResource);
+ }
+
+ @Test
+ public void givenResourceExists_whenResourceIsRetrieved_thenNoExceptions() {
+ final Foo existingResource = persistNewEntity();
+ getApi().findOne(existingResource.getId());
+ }
+
+ @Test
+ public void givenResourceDoesNotExist_whenResourceIsRetrieved_thenNoExceptions() {
+ getApi().findOne(IDUtil.randomPositiveLong());
+ }
+
+ @Test
+ public void givenResourceExists_whenResourceIsRetrieved_thenTheResultIsNotNull() {
+ final Foo existingResource = persistNewEntity();
+ final Foo retrievedResource = getApi().findOne(existingResource.getId());
+ assertNotNull(retrievedResource);
+ }
+
+ @Test
+ public void givenResourceExists_whenResourceIsRetrieved_thenResourceIsRetrievedCorrectly() {
+ final Foo existingResource = persistNewEntity();
+ final Foo retrievedResource = getApi().findOne(existingResource.getId());
+ assertEquals(existingResource, retrievedResource);
+ }
+
+ // find - one - by name
+
+ // find - all
+
+ @Test
+ /**/public void whenAllResourcesAreRetrieved_thenNoExceptions() {
+ getApi().findAll();
+ }
+
+ @Test
+ /**/public void whenAllResourcesAreRetrieved_thenTheResultIsNotNull() {
+ final List resources = getApi().findAll();
+
+ assertNotNull(resources);
+ }
+
+ @Test
+ /**/public void givenAtLeastOneResourceExists_whenAllResourcesAreRetrieved_thenRetrievedResourcesAreNotEmpty() {
+ persistNewEntity();
+
+ // When
+ final List allResources = getApi().findAll();
+
+ // Then
+ assertThat(allResources, not(Matchers. empty()));
+ }
+
+ @Test
+ /**/public void givenAnResourceExists_whenAllResourcesAreRetrieved_thenTheExistingResourceIsIndeedAmongThem() {
+ final Foo existingResource = persistNewEntity();
+
+ final List resources = getApi().findAll();
+
+ assertThat(resources, hasItem(existingResource));
+ }
+
+ @Test
+ /**/public void whenAllResourcesAreRetrieved_thenResourcesHaveIds() {
+ persistNewEntity();
+
+ // When
+ final List allResources = getApi().findAll();
+
+ // Then
+ for (final Foo resource : allResources) {
+ assertNotNull(resource.getId());
+ }
+ }
+
+ // create
+
+ @Test(expected = RuntimeException.class)
+ /**/public void whenNullResourceIsCreated_thenException() {
+ getApi().create(null);
+ }
+
+ @Test
+ /**/public void whenResourceIsCreated_thenNoExceptions() {
+ persistNewEntity();
+ }
+
+ @Test
+ /**/public void whenResourceIsCreated_thenResourceIsRetrievable() {
+ final Foo existingResource = persistNewEntity();
+
+ assertNotNull(getApi().findOne(existingResource.getId()));
+ }
+
+ @Test
+ /**/public void whenResourceIsCreated_thenSavedResourceIsEqualToOriginalResource() {
+ final Foo originalResource = createNewEntity();
+ final Foo savedResource = getApi().create(originalResource);
+
+ assertEquals(originalResource, savedResource);
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void whenResourceWithFailedConstraintsIsCreated_thenException() {
+ final Foo invalidResource = createNewEntity();
+ invalidate(invalidResource);
+
+ getApi().create(invalidResource);
+ }
+
+ /**
+ * -- specific to the persistence engine
+ */
+ @Test(expected = DataAccessException.class)
+ @Ignore("Hibernate simply ignores the id silently and still saved (tracking this)")
+ public void whenResourceWithIdIsCreated_thenDataAccessException() {
+ final Foo resourceWithId = createNewEntity();
+ resourceWithId.setId(IDUtil.randomPositiveLong());
+
+ getApi().create(resourceWithId);
+ }
+
+ // update
+
+ @Test(expected = RuntimeException.class)
+ /**/public void whenNullResourceIsUpdated_thenException() {
+ getApi().update(null);
+ }
+
+ @Test
+ /**/public void givenResourceExists_whenResourceIsUpdated_thenNoExceptions() {
+ // Given
+ final Foo existingResource = persistNewEntity();
+
+ // When
+ getApi().update(existingResource);
+ }
+
+ /**
+ * - can also be the ConstraintViolationException which now occurs on the update operation will not be translated; as a consequence, it will be a TransactionSystemException
+ */
+ @Test(expected = RuntimeException.class)
+ public void whenResourceIsUpdatedWithFailedConstraints_thenException() {
+ final Foo existingResource = persistNewEntity();
+ invalidate(existingResource);
+
+ getApi().update(existingResource);
+ }
+
+ @Test
+ /**/public void givenResourceExists_whenResourceIsUpdated_thenUpdatesArePersisted() {
+ // Given
+ final Foo existingResource = persistNewEntity();
+
+ // When
+ change(existingResource);
+ getApi().update(existingResource);
+
+ final Foo updatedResource = getApi().findOne(existingResource.getId());
+
+ // Then
+ assertEquals(existingResource, updatedResource);
+ }
+
+ // delete
+
+ // @Test(expected = RuntimeException.class)
+ // public void givenResourceDoesNotExists_whenResourceIsDeleted_thenException() {
+ // // When
+ // getApi().delete(IDUtil.randomPositiveLong());
+ // }
+ //
+ // @Test(expected = RuntimeException.class)
+ // public void whenResourceIsDeletedByNegativeId_thenException() {
+ // // When
+ // getApi().delete(IDUtil.randomNegativeLong());
+ // }
+ //
+ // @Test
+ // public void givenResourceExists_whenResourceIsDeleted_thenNoExceptions() {
+ // // Given
+ // final Foo existingResource = persistNewEntity();
+ //
+ // // When
+ // getApi().delete(existingResource.getId());
+ // }
+ //
+ // @Test
+ // /**/public final void givenResourceExists_whenResourceIsDeleted_thenResourceNoLongerExists() {
+ // // Given
+ // final Foo existingResource = persistNewEntity();
+ //
+ // // When
+ // getApi().delete(existingResource.getId());
+ //
+ // // Then
+ // assertNull(getApi().findOne(existingResource.getId()));
+ // }
+
+ // template method
+
+ protected Foo createNewEntity() {
+ return new Foo(randomAlphabetic(6));
+ }
+
+ protected abstract IOperations getApi();
+
+ private final void invalidate(final Foo entity) {
+ entity.setName(null);
+ }
+
+ private final void change(final Foo entity) {
+ entity.setName(randomAlphabetic(6));
+ }
+
+ protected Foo persistNewEntity() {
+ return getApi().create(createNewEntity());
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/service/FooServicePersistenceIntegrationTest.java b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/service/FooServicePersistenceIntegrationTest.java
new file mode 100644
index 0000000000..8184a2320a
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/java/org/baeldung/spring/data/persistence/service/FooServicePersistenceIntegrationTest.java
@@ -0,0 +1,77 @@
+package org.baeldung.spring.data.persistence.service;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+import static org.junit.Assert.assertNotNull;
+
+import org.baeldung.spring.data.persistence.model.Foo;
+import org.baeldung.spring.data.persistence.config.PersistenceConfig;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+import com.baeldung.persistence.dao.common.IOperations;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class FooServicePersistenceIntegrationTest extends AbstractServicePersistenceIntegrationTest {
+
+ @Autowired
+ private IFooService service;
+
+ // tests
+
+ @Test
+ public final void whenContextIsBootstrapped_thenNoExceptions() {
+ //
+ }
+
+ @Test
+ public final void whenEntityIsCreated_thenNoExceptions() {
+ service.create(new Foo(randomAlphabetic(6)));
+ }
+
+ @Test(expected = DataIntegrityViolationException.class)
+ public final void whenInvalidEntityIsCreated_thenDataException() {
+ service.create(new Foo());
+ }
+
+ @Test(expected = DataIntegrityViolationException.class)
+ public final void whenEntityWithLongNameIsCreated_thenDataException() {
+ service.create(new Foo(randomAlphabetic(2048)));
+ }
+
+ // custom Query method
+
+ @Test
+ public final void givenUsingCustomQuery_whenRetrievingEntity_thenFound() {
+ final String name = randomAlphabetic(6);
+ service.create(new Foo(name));
+
+ final Foo retrievedByName = service.retrieveByName(name);
+ assertNotNull(retrievedByName);
+ }
+
+ // work in progress
+
+ @Test(expected = InvalidDataAccessApiUsageException.class)
+ @Ignore("Right now, persist has saveOrUpdate semantics, so this will no longer fail")
+ public final void whenSameEntityIsCreatedTwice_thenDataException() {
+ final Foo entity = new Foo(randomAlphabetic(8));
+ service.create(entity);
+ service.create(entity);
+ }
+
+ // API
+
+ @Override
+ protected final IOperations getApi() {
+ return service;
+ }
+
+}
diff --git a/persistence-modules/spring-persistence-simple/src/test/resources/.gitignore b/persistence-modules/spring-persistence-simple/src/test/resources/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/persistence-modules/spring-persistence-simple/src/test/resources/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 89c9416ebb..9298c8ad17 100644
--- a/pom.xml
+++ b/pom.xml
@@ -608,6 +608,7 @@
spring-5-reactive-security
spring-5-security
spring-5-security-oauth
+ spring-5-security-cognito
spring-activiti
spring-akka
@@ -634,7 +635,6 @@
spring-boot-custom-starter
spring-boot-disable-console-logging
- spring-boot-exceptions
spring-boot-jasypt
spring-boot-keycloak
spring-boot-logging-log4j2
@@ -819,6 +819,7 @@
spring-5-reactive-security
spring-5-security
spring-5-security-oauth
+ spring-5-security-cognito
spring-activiti
spring-akka
spring-all
@@ -832,7 +833,6 @@
spring-boot-camel
spring-boot-client
spring-boot-custom-starter
- spring-boot-exceptions
greeter-spring-boot-autoconfigure
greeter-spring-boot-sample-app
persistence-modules/spring-boot-h2/spring-boot-h2-database
@@ -1271,7 +1271,7 @@
spring-5-reactive-security
spring-5-security
spring-5-security-oauth
-
+ spring-5-security-cognito
spring-activiti
spring-akka
spring-all
@@ -1295,7 +1295,6 @@
spring-boot-ctx-fluent
spring-boot-custom-starter
spring-boot-disable-console-logging
- spring-boot-exceptions
spring-boot-jasypt
spring-boot-keycloak
diff --git a/rule-engines/easy-rules/pom.xml b/rule-engines/easy-rules/pom.xml
index 5b88ce4e94..369451c56c 100644
--- a/rule-engines/easy-rules/pom.xml
+++ b/rule-engines/easy-rules/pom.xml
@@ -10,6 +10,7 @@
com.baeldung
parent-modules
1.0.0-SNAPSHOT
+ ../..
@@ -23,4 +24,4 @@
3.0.0
-
\ No newline at end of file
+
diff --git a/rule-engines/openl-tablets/pom.xml b/rule-engines/openl-tablets/pom.xml
index 3bd6055fc9..b19ec8d3f1 100644
--- a/rule-engines/openl-tablets/pom.xml
+++ b/rule-engines/openl-tablets/pom.xml
@@ -10,6 +10,7 @@
com.baeldung
parent-modules
1.0.0-SNAPSHOT
+ ../..
@@ -29,4 +30,4 @@
5.19.4
-
\ No newline at end of file
+
diff --git a/rule-engines/rulebook/pom.xml b/rule-engines/rulebook/pom.xml
index 90b5e55417..5e0b900bd9 100644
--- a/rule-engines/rulebook/pom.xml
+++ b/rule-engines/rulebook/pom.xml
@@ -10,6 +10,7 @@
com.baeldung
parent-modules
1.0.0-SNAPSHOT
+ ../..
@@ -24,4 +25,4 @@
0.6.2
-
\ No newline at end of file
+
diff --git a/spring-5-security-cognito/README.md b/spring-5-security-cognito/README.md
new file mode 100644
index 0000000000..0825882c05
--- /dev/null
+++ b/spring-5-security-cognito/README.md
@@ -0,0 +1,3 @@
+## Relevant articles:
+
+- [Authenticating with Amazon Cognito Using Spring Security](https://www.baeldung.com/spring-security-oauth-cognito)
diff --git a/spring-5-security-cognito/pom.xml b/spring-5-security-cognito/pom.xml
new file mode 100644
index 0000000000..c7314d6f9f
--- /dev/null
+++ b/spring-5-security-cognito/pom.xml
@@ -0,0 +1,74 @@
+
+ 4.0.0
+ com.baeldung
+ spring-5-security-cognito
+ 0.0.1-SNAPSHOT
+ spring-5-security-cognito
+ jar
+ spring 5 security oauth cognito sample project
+
+
+ com.baeldung
+ parent-boot-2
+ 0.0.1-SNAPSHOT
+ ../parent-boot-2
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ org.thymeleaf.extras
+ thymeleaf-extras-springsecurity5
+
+
+
+
+ org.springframework.security.oauth.boot
+ spring-security-oauth2-autoconfigure
+ ${oauth-auto.version}
+
+
+ org.springframework.security
+ spring-security-oauth2-client
+
+
+ org.springframework.security
+ spring-security-oauth2-jose
+
+
+
+ org.springframework
+ spring-test
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.security
+ spring-security-test
+ test
+
+
+
+
+ 2.1.0.RELEASE
+ 2.1.0.RELEASE
+ com.baeldung.cognito.SpringCognitoApplication
+
+
+
diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java b/spring-5-security-cognito/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java
similarity index 91%
rename from spring-5-security-oauth/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java
rename to spring-5-security-cognito/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java
index ae03e0a802..6841fa7a65 100644
--- a/spring-5-security-oauth/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java
+++ b/spring-5-security-cognito/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java
@@ -6,7 +6,7 @@ import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
-@PropertySource("cognito/application_cognito.yml")
+@PropertySource("cognito/application-cognito.yml")
public class CognitoWebConfiguration implements WebMvcConfigurer {
@Override
diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java b/spring-5-security-cognito/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java
similarity index 88%
rename from spring-5-security-oauth/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java
rename to spring-5-security-cognito/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java
index 7f7b751cd9..eebe6d8f45 100644
--- a/spring-5-security-oauth/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java
+++ b/spring-5-security-cognito/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java
@@ -5,7 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;
@SpringBootApplication
-@PropertySource("cognito/application_cognito.yml")
+@PropertySource("cognito/application-cognito.yml")
public class SpringCognitoApplication {
public static void main(String[] args) {
diff --git a/spring-5-security-oauth/src/main/resources/cognito/application_cognito.yml b/spring-5-security-cognito/src/main/resources/cognito/application-cognito.yml
similarity index 100%
rename from spring-5-security-oauth/src/main/resources/cognito/application_cognito.yml
rename to spring-5-security-cognito/src/main/resources/cognito/application-cognito.yml
diff --git a/spring-5-security-oauth/src/main/resources/cognito/home.html b/spring-5-security-cognito/src/main/resources/cognito/home.html
similarity index 100%
rename from spring-5-security-oauth/src/main/resources/cognito/home.html
rename to spring-5-security-cognito/src/main/resources/cognito/home.html
diff --git a/spring-5-security-oauth/src/main/resources/cognito/style.css b/spring-5-security-cognito/src/main/resources/cognito/style.css
similarity index 100%
rename from spring-5-security-oauth/src/main/resources/cognito/style.css
rename to spring-5-security-cognito/src/main/resources/cognito/style.css
diff --git a/spring-5-security-cognito/src/main/resources/logback.xml b/spring-5-security-cognito/src/main/resources/logback.xml
new file mode 100644
index 0000000000..7d900d8ea8
--- /dev/null
+++ b/spring-5-security-cognito/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/spring-5-webflux/README.md b/spring-5-webflux/README.md
index 4345c8746b..e84ee863bf 100644
--- a/spring-5-webflux/README.md
+++ b/spring-5-webflux/README.md
@@ -2,4 +2,4 @@
- [Spring Boot Reactor Netty Configuration](https://www.baeldung.com/spring-boot-reactor-netty)
- [How to Return 404 with Spring WebFlux](https://www.baeldung.com/spring-webflux-404)
-- [WebClient request with parameters](https://www.baeldung.com/webclient-request-with-parameters)
+- [Spring WebClient Requests with Parameters](https://www.baeldung.com/webflux-webclient-parameters)
diff --git a/spring-boot-data/README.md b/spring-boot-data/README.md
index d93b8c3e93..3fd1d17994 100644
--- a/spring-boot-data/README.md
+++ b/spring-boot-data/README.md
@@ -1,2 +1,3 @@
### Relevant Articles:
- [Formatting JSON Dates in Spring Boot](https://www.baeldung.com/spring-boot-formatting-json-dates)
+- [Rendering Exceptions in JSON with Spring](https://www.baeldung.com/spring-exceptions-json)
diff --git a/spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/CustomException.java b/spring-boot-data/src/main/java/com/baeldung/jsonexception/CustomException.java
similarity index 100%
rename from spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/CustomException.java
rename to spring-boot-data/src/main/java/com/baeldung/jsonexception/CustomException.java
diff --git a/spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/ErrorHandler.java b/spring-boot-data/src/main/java/com/baeldung/jsonexception/ErrorHandler.java
similarity index 73%
rename from spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/ErrorHandler.java
rename to spring-boot-data/src/main/java/com/baeldung/jsonexception/ErrorHandler.java
index a890dfa3a2..9f82c4fc57 100644
--- a/spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/ErrorHandler.java
+++ b/spring-boot-data/src/main/java/com/baeldung/jsonexception/ErrorHandler.java
@@ -1,13 +1,11 @@
package com.baeldung.jsonexception;
import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
-@ControllerAdvice
-@ResponseBody
+@RestControllerAdvice
public class ErrorHandler {
@ExceptionHandler(CustomException.class)
diff --git a/spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/MainController.java b/spring-boot-data/src/main/java/com/baeldung/jsonexception/MainController.java
similarity index 100%
rename from spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/MainController.java
rename to spring-boot-data/src/main/java/com/baeldung/jsonexception/MainController.java
diff --git a/spring-boot-exceptions/src/test/java/com/baeldung/jsonexception/MainControllerIntegrationTest.java b/spring-boot-data/src/test/java/com/baeldung/jsonexception/MainControllerIntegrationTest.java
similarity index 100%
rename from spring-boot-exceptions/src/test/java/com/baeldung/jsonexception/MainControllerIntegrationTest.java
rename to spring-boot-data/src/test/java/com/baeldung/jsonexception/MainControllerIntegrationTest.java
diff --git a/spring-boot-exceptions/.gitignore b/spring-boot-exceptions/.gitignore
deleted file mode 100644
index 153c9335eb..0000000000
--- a/spring-boot-exceptions/.gitignore
+++ /dev/null
@@ -1,29 +0,0 @@
-HELP.md
-/target/
-!.mvn/wrapper/maven-wrapper.jar
-
-### STS ###
-.apt_generated
-.classpath
-.factorypath
-.project
-.settings
-.springBeans
-.sts4-cache
-
-### IntelliJ IDEA ###
-.idea
-*.iws
-*.iml
-*.ipr
-
-### NetBeans ###
-/nbproject/private/
-/nbbuild/
-/dist/
-/nbdist/
-/.nb-gradle/
-/build/
-
-### VS Code ###
-.vscode/
diff --git a/spring-boot-exceptions/README.md b/spring-boot-exceptions/README.md
new file mode 100644
index 0000000000..bbc272aec4
--- /dev/null
+++ b/spring-boot-exceptions/README.md
@@ -0,0 +1,4 @@
+
+### Relevant Articles:
+
+- [Rendering Exceptions in JSON with Spring](https://www.baeldung.com/spring-exceptions-json)
diff --git a/spring-boot-exceptions/pom.xml b/spring-boot-exceptions/pom.xml
deleted file mode 100644
index 01d6973642..0000000000
--- a/spring-boot-exceptions/pom.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
- 4.0.0
-
-
- com.baeldung
- parent-boot-2
- 0.0.1-SNAPSHOT
- ../parent-boot-2
-
-
- com.baeldung
- spring-boot-exceptions
- 0.0.4-SNAPSHOT
- pass-exception-to-client-json-spring-boot
- Baeldung article code on how to pass exceptions to client in JSON format using Spring Boot
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
-
-
diff --git a/spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/JsonErrorApplication.java b/spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/JsonErrorApplication.java
deleted file mode 100644
index 188584bd7c..0000000000
--- a/spring-boot-exceptions/src/main/java/com/baeldung/jsonexception/JsonErrorApplication.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.baeldung.jsonexception;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-@SpringBootApplication
-public class JsonErrorApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(JsonErrorApplication.class, args);
- }
-
-}
\ No newline at end of file
diff --git a/spring-boot-exceptions/src/main/resources/application.properties b/spring-boot-exceptions/src/main/resources/application.properties
deleted file mode 100644
index 8b13789179..0000000000
--- a/spring-boot-exceptions/src/main/resources/application.properties
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/spring-boot-exceptions/src/main/resources/static/.gitignore b/spring-boot-exceptions/src/main/resources/static/.gitignore
deleted file mode 100644
index 5e7d2734cf..0000000000
--- a/spring-boot-exceptions/src/main/resources/static/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-# Ignore everything in this directory
-*
-# Except this file
-!.gitignore
diff --git a/spring-boot-exceptions/src/main/resources/templates/.gitignore b/spring-boot-exceptions/src/main/resources/templates/.gitignore
deleted file mode 100644
index 5e7d2734cf..0000000000
--- a/spring-boot-exceptions/src/main/resources/templates/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-# Ignore everything in this directory
-*
-# Except this file
-!.gitignore
diff --git a/spring-boot-exceptions/src/test/java/com/baeldung/jsonexception/SpringContextIntegrationTest.java b/spring-boot-exceptions/src/test/java/com/baeldung/jsonexception/SpringContextIntegrationTest.java
deleted file mode 100644
index aa91e242ab..0000000000
--- a/spring-boot-exceptions/src/test/java/com/baeldung/jsonexception/SpringContextIntegrationTest.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.baeldung.jsonexception;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.junit4.SpringRunner;
-
-@RunWith(SpringRunner.class)
-@SpringBootTest
-public class SpringContextIntegrationTest {
-
- @Test
- public void contextLoads() {
- }
-
-}
diff --git a/spring-boot-ops/README.md b/spring-boot-ops/README.md
index d5063f14e5..5be5c974d3 100644
--- a/spring-boot-ops/README.md
+++ b/spring-boot-ops/README.md
@@ -11,4 +11,4 @@
- [Comparing Embedded Servlet Containers in Spring Boot](http://www.baeldung.com/spring-boot-servlet-containers)
- [Programmatically Restarting a Spring Boot Application](https://www.baeldung.com/java-restart-spring-boot-app)
- [Spring Properties File Outside jar](https://www.baeldung.com/spring-properties-file-outside-jar)
-
+ - [EnvironmentPostProcessor in Spring Boot](https://www.baeldung.com/spring-boot-environmentpostprocessor)
diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md
index b28192cf62..6f365bd465 100644
--- a/spring-boot-rest/README.md
+++ b/spring-boot-rest/README.md
@@ -16,3 +16,4 @@ Module for the articles that are part of the Spring REST E-book:
- [ETags for REST with Spring](http://www.baeldung.com/etags-for-rest-with-spring)
- [Testing REST with multiple MIME types](http://www.baeldung.com/testing-rest-api-with-multiple-media-types)
- [Testing Web APIs with Postman Collections](https://www.baeldung.com/postman-testing-collections)
+- [Spring Boot Consuming and Producing JSON](https://www.baeldung.com/spring-boot-json)
diff --git a/spring-boot-testing/README.MD b/spring-boot-testing/README.MD
index 144c3581f7..99d7db5743 100644
--- a/spring-boot-testing/README.MD
+++ b/spring-boot-testing/README.MD
@@ -5,3 +5,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Testing with Spring and Spock](https://www.baeldung.com/spring-spock-testing)
- [Exclude Auto-Configuration Classes in Spring Boot Tests](https://www.baeldung.com/spring-boot-exclude-auto-configuration-test)
+- [Setting the Log Level in Spring Boot when Testing](https://www.baeldung.com/spring-boot-testing-log-level)
diff --git a/spring-boot/README.MD b/spring-boot/README.MD
index c0392d38de..d7af3f4614 100644
--- a/spring-boot/README.MD
+++ b/spring-boot/README.MD
@@ -36,3 +36,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Injecting Git Information Into Spring](https://www.baeldung.com/spring-git-information)
- [Validation in Spring Boot](https://www.baeldung.com/spring-boot-bean-validation)
- [Guide to Creating and Running a Jar File in Java](https://www.baeldung.com/java-create-jar)
+- [Entity To DTO Conversion for a Spring REST API](https://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application)
diff --git a/spring-cloud-data-flow/README.MD b/spring-cloud-data-flow/README.MD
index 17d0ec6286..9e5cef19af 100644
--- a/spring-cloud-data-flow/README.MD
+++ b/spring-cloud-data-flow/README.MD
@@ -1,3 +1,4 @@
### Relevant Articles:
- [Batch Processing with Spring Cloud Data Flow](http://www.baeldung.com/spring-cloud-data-flow-batch-processing)
- [Getting Started with Stream Processing with Spring Cloud Data Flow](http://www.baeldung.com/spring-cloud-data-flow-stream-processing)
+- [Spring Cloud Data Flow With Apache Spark](https://www.baeldung.com/spring-cloud-data-flow-spark)
diff --git a/spring-cloud/spring-cloud-eureka/pom.xml b/spring-cloud/spring-cloud-eureka/pom.xml
index 924981765c..e8e3d67805 100644
--- a/spring-cloud/spring-cloud-eureka/pom.xml
+++ b/spring-cloud/spring-cloud-eureka/pom.xml
@@ -32,8 +32,8 @@
- 2.0.1.RELEASE
- Finchley.SR2
+ 2.1.2.RELEASE
+ Greenwich.RELEASE
diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml
index 85fa6606d2..04a5bd3e58 100644
--- a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml
+++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml
@@ -19,12 +19,10 @@
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
- ${spring-cloud-starter-eureka.version}
org.springframework.boot
spring-boot-starter-web
- ${spring-boot.version}
diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml
index 84ba1e28fe..acc436c574 100644
--- a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml
+++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml
@@ -18,23 +18,19 @@
org.springframework.cloud
- spring-cloud-starter-feign
- ${spring-cloud-starter-feign.version}
+ spring-cloud-starter-openfeign
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
- ${spring-cloud-starter-eureka.version}
org.springframework.boot
spring-boot-starter-web
- ${spring-boot.version}
org.springframework.boot
spring-boot-starter-thymeleaf
- ${spring-boot.version}
@@ -49,8 +45,4 @@
-
-
- 1.0.0-SNAPSHOT
-
diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml
index f51f6d229d..95edba29f9 100644
--- a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml
+++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml
@@ -19,7 +19,6 @@
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
- ${spring-cloud-starter-eureka.version}
diff --git a/spring-cloud/spring-cloud-kubernetes/README.md b/spring-cloud/spring-cloud-kubernetes/README.md
index 2387758626..32bcbc59b8 100644
--- a/spring-cloud/spring-cloud-kubernetes/README.md
+++ b/spring-cloud/spring-cloud-kubernetes/README.md
@@ -2,3 +2,4 @@
- [Running Spring Boot Applications With Minikube](https://www.baeldung.com/spring-boot-minikube)
- [Self-Healing Applications with Kubernetes and Spring Boot](https://www.baeldung.com/spring-boot-kubernetes-self-healing-apps)
+- [Guide to Spring Cloud Kubernetes](https://www.baeldung.com/spring-cloud-kubernetes)
diff --git a/spring-mvc-simple-2/README.md b/spring-mvc-simple-2/README.md
new file mode 100644
index 0000000000..6dfe789be4
--- /dev/null
+++ b/spring-mvc-simple-2/README.md
@@ -0,0 +1,2 @@
+## Relevant articles:
+- [How to Read HTTP Headers in Spring REST Controllers](https://www.baeldung.com/spring-rest-http-headers)
diff --git a/spring-mvc-simple/README.md b/spring-mvc-simple/README.md
index cd4ad5aba2..755e0932fc 100644
--- a/spring-mvc-simple/README.md
+++ b/spring-mvc-simple/README.md
@@ -8,4 +8,3 @@
- [Guide to Spring Email](http://www.baeldung.com/spring-email)
- [Request Method Not Supported (405) in Spring](https://www.baeldung.com/spring-request-method-not-supported-405)
- [Spring @RequestParam Annotation](https://www.baeldung.com/spring-request-param)
-- [Validating RequestParams and PathVariables in Spring](https://www.baeldung.com/spring-validate-requestparam-pathvariable)
diff --git a/spring-mvc-xml/README.md b/spring-mvc-xml/README.md
index 216517f52d..c8ec074d17 100644
--- a/spring-mvc-xml/README.md
+++ b/spring-mvc-xml/README.md
@@ -15,3 +15,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Exploring SpringMVC’s Form Tag Library](http://www.baeldung.com/spring-mvc-form-tags)
- [web.xml vs Initializer with Spring](http://www.baeldung.com/spring-xml-vs-java-config)
- [A Java Web Application Without a web.xml](https://www.baeldung.com/java-web-app-without-web-xml)
+- [Validating RequestParams and PathVariables in Spring](https://www.baeldung.com/spring-validate-requestparam-pathvariable)
\ No newline at end of file
diff --git a/spring-mvc-xml/pom.xml b/spring-mvc-xml/pom.xml
index beea8e5ee2..46af321d1b 100644
--- a/spring-mvc-xml/pom.xml
+++ b/spring-mvc-xml/pom.xml
@@ -1,4 +1,5 @@
-
4.0.0
0.1-SNAPSHOT
@@ -20,12 +21,6 @@
org.springframework
spring-web
${org.springframework.version}
-
-
- commons-logging
- commons-logging
-
-
org.springframework
@@ -50,7 +45,7 @@
- org.hibernate
+ org.hibernate.validator
hibernate-validator
${hibernate-validator.version}
@@ -84,6 +79,11 @@
+
+ org.glassfish
+ javax.el
+ 3.0.1-b08
+
org.springframework.boot
diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java
index 7925fa451d..09c34ccc80 100644
--- a/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java
+++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java
@@ -5,8 +5,10 @@ import java.util.ResourceBundle;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.MessageSourceResourceBundle;
import org.springframework.context.support.ResourceBundleMessageSource;
+import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@@ -15,6 +17,7 @@ import org.springframework.web.servlet.view.JstlView;
//@EnableWebMvc
//@Configuration
+@ComponentScan("com.baeldung.spring")
public class ClientWebConfigJava implements WebMvcConfigurer {
public ClientWebConfigJava() {
@@ -51,4 +54,9 @@ public class ClientWebConfigJava implements WebMvcConfigurer {
return bean;
}
+
+ @Bean
+ public MethodValidationPostProcessor methodValidationPostProcessor() {
+ return new MethodValidationPostProcessor();
+ }
}
\ No newline at end of file
diff --git a/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java
index 318a15d8f7..c4332dd879 100644
--- a/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java
+++ b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java
@@ -12,12 +12,13 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import com.baeldung.spring.ClientWebConfig;
+import com.baeldung.spring.ClientWebConfigJava;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = ClientWebConfig.class)
+@ContextConfiguration(classes = ClientWebConfigJava.class)
@WebAppConfiguration
public class RequestAndPathVariableValidationControllerIntegrationTest {
diff --git a/spring-rest-full/README.md b/spring-rest-full/README.md
index e0d3a70626..b7b006d75e 100644
--- a/spring-rest-full/README.md
+++ b/spring-rest-full/README.md
@@ -9,7 +9,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
### Relevant Articles:
- [Integration Testing with the Maven Cargo plugin](http://www.baeldung.com/integration-testing-with-the-maven-cargo-plugin)
-- [Introduction to Spring Data JPA](http://www.baeldung.com/the-persistence-layer-with-spring-data-jpa)
- [Project Configuration with Spring](http://www.baeldung.com/project-configuration-with-spring)
- [Metrics for your Spring REST API](http://www.baeldung.com/spring-rest-api-metrics)
- [Spring Security Expressions - hasRole Example](https://www.baeldung.com/spring-security-expressions-basic)
diff --git a/spring-rest-full/pom.xml b/spring-rest-full/pom.xml
index ee6e5dbe3e..a85393b7a8 100644
--- a/spring-rest-full/pom.xml
+++ b/spring-rest-full/pom.xml
@@ -8,10 +8,10 @@
war
- parent-boot-1
+ parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../parent-boot-1
+ ../parent-boot-2
@@ -129,6 +129,7 @@
org.javassist
javassist
+ ${javassist.version}
mysql
@@ -287,6 +288,7 @@
19.0
3.5
+ 3.25.0-GA
1.6.1
diff --git a/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java b/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java
index 059516eeba..ceefbbe0e3 100644
--- a/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java
+++ b/spring-rest-full/src/main/java/org/baeldung/persistence/service/common/AbstractService.java
@@ -17,7 +17,7 @@ public abstract class AbstractService implements IOperat
@Override
@Transactional(readOnly = true)
public T findOne(final long id) {
- return getDao().findOne(id);
+ return getDao().findById(id).orElse(null);
}
// read - all
diff --git a/spring-rest-full/src/main/java/org/baeldung/spring/Application.java b/spring-rest-full/src/main/java/org/baeldung/spring/Application.java
index 950e2085a6..ca72a4ef56 100644
--- a/spring-rest-full/src/main/java/org/baeldung/spring/Application.java
+++ b/spring-rest-full/src/main/java/org/baeldung/spring/Application.java
@@ -7,7 +7,7 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.boot.web.support.SpringBootServletInitializer;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.context.request.RequestContextListener;
diff --git a/spring-rest-full/src/main/java/org/baeldung/spring/WebConfig.java b/spring-rest-full/src/main/java/org/baeldung/spring/WebConfig.java
index 86cb93175a..a0db08d93d 100644
--- a/spring-rest-full/src/main/java/org/baeldung/spring/WebConfig.java
+++ b/spring-rest-full/src/main/java/org/baeldung/spring/WebConfig.java
@@ -6,13 +6,13 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@ComponentScan("org.baeldung.web")
@EnableWebMvc
-public class WebConfig extends WebMvcConfigurerAdapter {
+public class WebConfig implements WebMvcConfigurer {
public WebConfig() {
super();
@@ -29,7 +29,6 @@ public class WebConfig extends WebMvcConfigurerAdapter {
// API
@Override
public void addViewControllers(final ViewControllerRegistry registry) {
- super.addViewControllers(registry);
registry.addViewController("/graph.html");
registry.addViewController("/homepage.html");
}
diff --git a/spring-rest-full/src/main/java/org/baeldung/web/metric/ActuatorMetricService.java b/spring-rest-full/src/main/java/org/baeldung/web/metric/ActuatorMetricService.java
index 89e3a22d45..4dcec17b9e 100644
--- a/spring-rest-full/src/main/java/org/baeldung/web/metric/ActuatorMetricService.java
+++ b/spring-rest-full/src/main/java/org/baeldung/web/metric/ActuatorMetricService.java
@@ -6,16 +6,18 @@ import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.actuate.endpoint.MetricReaderPublicMetrics;
-import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
+import io.micrometer.core.instrument.Counter;
+import io.micrometer.core.instrument.Meter;
+import io.micrometer.core.instrument.MeterRegistry;
+
@Service
public class ActuatorMetricService implements IActuatorMetricService {
@Autowired
- private MetricReaderPublicMetrics publicMetrics;
+ private MeterRegistry publicMetrics;
private final List> statusMetricsByMinute;
private final List statusList;
@@ -68,7 +70,7 @@ public class ActuatorMetricService implements IActuatorMetricService {
private void exportMetrics() {
final ArrayList lastMinuteStatuses = initializeStatuses(statusList.size());
- for (final Metric> counterMetric : publicMetrics.metrics()) {
+ for (final Meter counterMetric : publicMetrics.getMeters()) {
updateMetrics(counterMetric, lastMinuteStatuses);
}
@@ -83,17 +85,17 @@ public class ActuatorMetricService implements IActuatorMetricService {
return counterList;
}
- private void updateMetrics(final Metric> counterMetric, final ArrayList statusCount) {
+ private void updateMetrics(final Meter counterMetric, final ArrayList statusCount) {
String status = "";
int index = -1;
int oldCount = 0;
- if (counterMetric.getName().contains("counter.status.")) {
- status = counterMetric.getName().substring(15, 18); // example 404, 200
+ if (counterMetric.getId().getName().contains("counter.status.")) {
+ status = counterMetric.getId().getName().substring(15, 18); // example 404, 200
appendStatusIfNotExist(status, statusCount);
index = statusList.indexOf(status);
oldCount = statusCount.get(index) == null ? 0 : statusCount.get(index);
- statusCount.set(index, counterMetric.getValue().intValue() + oldCount);
+ statusCount.set(index, (int)((Counter) counterMetric).count() + oldCount);
}
}
diff --git a/spring-rest-full/src/main/java/org/baeldung/web/metric/CustomActuatorMetricService.java b/spring-rest-full/src/main/java/org/baeldung/web/metric/CustomActuatorMetricService.java
index 852a9fae99..cf30686e52 100644
--- a/spring-rest-full/src/main/java/org/baeldung/web/metric/CustomActuatorMetricService.java
+++ b/spring-rest-full/src/main/java/org/baeldung/web/metric/CustomActuatorMetricService.java
@@ -6,20 +6,18 @@ import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.actuate.metrics.CounterService;
-import org.springframework.boot.actuate.metrics.Metric;
-import org.springframework.boot.actuate.metrics.repository.InMemoryMetricRepository;
-import org.springframework.boot.actuate.metrics.repository.MetricRepository;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
+import io.micrometer.core.instrument.Counter;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.search.Search;
+
@Service
public class CustomActuatorMetricService implements ICustomActuatorMetricService {
- private MetricRepository repo;
-
@Autowired
- private CounterService counter;
+ private MeterRegistry registry;
private final List> statusMetricsByMinute;
private final List statusList;
@@ -27,7 +25,6 @@ public class CustomActuatorMetricService implements ICustomActuatorMetricService
public CustomActuatorMetricService() {
super();
- repo = new InMemoryMetricRepository();
statusMetricsByMinute = new ArrayList>();
statusList = new ArrayList();
}
@@ -36,9 +33,10 @@ public class CustomActuatorMetricService implements ICustomActuatorMetricService
@Override
public void increaseCount(final int status) {
- counter.increment("status." + status);
- if (!statusList.contains("counter.status." + status)) {
- statusList.add("counter.status." + status);
+ String counterName = "counter.status." + status;
+ registry.counter(counterName).increment(1);
+ if (!statusList.contains(counterName)) {
+ statusList.add(counterName);
}
}
@@ -78,17 +76,16 @@ public class CustomActuatorMetricService implements ICustomActuatorMetricService
@Scheduled(fixedDelay = 60000)
private void exportMetrics() {
- Metric> metric;
final ArrayList statusCount = new ArrayList();
for (final String status : statusList) {
- metric = repo.findOne(status);
- if (metric != null) {
- statusCount.add(metric.getValue().intValue());
- repo.reset(status);
+ Search search = registry.find(status);
+ if (search != null) {
+ Counter counter = search.counter();
+ statusCount.add(counter != null ? ((int) counter.count()) : 0);
+ registry.remove(counter);
} else {
statusCount.add(0);
}
-
}
statusMetricsByMinute.add(statusCount);
}
diff --git a/spring-rest-full/src/main/resources/application.properties b/spring-rest-full/src/main/resources/application.properties
index 6c7461f12c..52d93b4cff 100644
--- a/spring-rest-full/src/main/resources/application.properties
+++ b/spring-rest-full/src/main/resources/application.properties
@@ -1,3 +1,3 @@
server.port=8082
-server.context-path=/spring-rest-full
+server.servlet.context-path=/spring-rest-full
endpoints.metrics.enabled=true
\ No newline at end of file
diff --git a/spring-security-mvc-socket/README.md b/spring-security-mvc-socket/README.md
index 6c2ad7b985..d3f28af387 100644
--- a/spring-security-mvc-socket/README.md
+++ b/spring-security-mvc-socket/README.md
@@ -8,3 +8,4 @@ To login, use credentials from the data.sql file in src/main/resource, eg: user/
### Relevant Articles:
- [Intro to Security and WebSockets](http://www.baeldung.com/spring-security-websockets)
- [Spring WebSockets: Build an User Chat](https://www.baeldung.com/spring-websockets-send-message-to-user)
+- [REST vs WebSockets](https://www.baeldung.com/rest-vs-websockets)
diff --git a/spring-security-sso/README.md b/spring-security-sso/README.md
index d0c1b2f7cf..88e3fbb2f7 100644
--- a/spring-security-sso/README.md
+++ b/spring-security-sso/README.md
@@ -1,2 +1,3 @@
### Relevant Articles:
- [Simple Single Sign-On with Spring Security OAuth2](http://www.baeldung.com/sso-spring-security-oauth2)
+- [Spring Security Kerberos Integration](https://www.baeldung.com/spring-security-kerberos-integration)
diff --git a/spring-security-sso/spring-security-sso-kerberos/README.md b/spring-security-sso/spring-security-sso-kerberos/README.md
new file mode 100644
index 0000000000..0227d9ac70
--- /dev/null
+++ b/spring-security-sso/spring-security-sso-kerberos/README.md
@@ -0,0 +1,4 @@
+## Relevant articles:
+
+- [Introduction to SPNEGO/Kerberos Authentication in Spring](https://www.baeldung.com/spring-security-kerberos)
+- [Spring Security Kerberos Integration](https://www.baeldung.com/spring-security-kerberos-integration)
diff --git a/testing-modules/junit-5-basics/README.md b/testing-modules/junit-5-basics/README.md
new file mode 100644
index 0000000000..a00e2a3f4a
--- /dev/null
+++ b/testing-modules/junit-5-basics/README.md
@@ -0,0 +1,3 @@
+### Relevant Articles:
+
+- [Get the Path of the /src/test/resources Directory in JUnit](https://www.baeldung.com/junit-src-test-resources-directory-path)
diff --git a/testing-modules/junit-5-configuration/pom.xml b/testing-modules/junit-5-basics/pom.xml
similarity index 97%
rename from testing-modules/junit-5-configuration/pom.xml
rename to testing-modules/junit-5-basics/pom.xml
index 0f19bc19b7..28afcd6aac 100644
--- a/testing-modules/junit-5-configuration/pom.xml
+++ b/testing-modules/junit-5-basics/pom.xml
@@ -3,10 +3,10 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
- junit-5-configuration
+ junit-5-basics
1.0-SNAPSHOT
- junit-5-configuration
- Intro to JUnit 5 configuration
+ junit-5-basics
+ Intro to JUnit 5
com.baeldung
diff --git a/testing-modules/junit-5-configuration/src/main/java/com/baeldung/junit/tags/example/Employee.java b/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/Employee.java
similarity index 100%
rename from testing-modules/junit-5-configuration/src/main/java/com/baeldung/junit/tags/example/Employee.java
rename to testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/Employee.java
diff --git a/testing-modules/junit-5-configuration/src/main/java/com/baeldung/junit/tags/example/EmployeeDAO.java b/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/EmployeeDAO.java
similarity index 100%
rename from testing-modules/junit-5-configuration/src/main/java/com/baeldung/junit/tags/example/EmployeeDAO.java
rename to testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/EmployeeDAO.java
diff --git a/testing-modules/junit-5-configuration/src/main/java/com/baeldung/junit/tags/example/EmployeeRowMapper.java b/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/EmployeeRowMapper.java
similarity index 100%
rename from testing-modules/junit-5-configuration/src/main/java/com/baeldung/junit/tags/example/EmployeeRowMapper.java
rename to testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/EmployeeRowMapper.java
diff --git a/testing-modules/junit-5-configuration/src/main/java/com/baeldung/junit/tags/example/SpringJdbcConfig.java b/testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/SpringJdbcConfig.java
similarity index 100%
rename from testing-modules/junit-5-configuration/src/main/java/com/baeldung/junit/tags/example/SpringJdbcConfig.java
rename to testing-modules/junit-5-basics/src/main/java/com/baeldung/junit/tags/example/SpringJdbcConfig.java
diff --git a/testing-modules/junit-5-configuration/src/main/resources/jdbc/schema.sql b/testing-modules/junit-5-basics/src/main/resources/jdbc/schema.sql
similarity index 100%
rename from testing-modules/junit-5-configuration/src/main/resources/jdbc/schema.sql
rename to testing-modules/junit-5-basics/src/main/resources/jdbc/schema.sql
diff --git a/testing-modules/junit-5-configuration/src/main/resources/jdbc/springJdbc-config.xml b/testing-modules/junit-5-basics/src/main/resources/jdbc/springJdbc-config.xml
similarity index 100%
rename from testing-modules/junit-5-configuration/src/main/resources/jdbc/springJdbc-config.xml
rename to testing-modules/junit-5-basics/src/main/resources/jdbc/springJdbc-config.xml
diff --git a/testing-modules/junit-5-configuration/src/main/resources/jdbc/test-data.sql b/testing-modules/junit-5-basics/src/main/resources/jdbc/test-data.sql
similarity index 100%
rename from testing-modules/junit-5-configuration/src/main/resources/jdbc/test-data.sql
rename to testing-modules/junit-5-basics/src/main/resources/jdbc/test-data.sql
diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/categories/EmployeeDAOCategoryIntegrationTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/EmployeeDAOCategoryIntegrationTest.java
similarity index 100%
rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/categories/EmployeeDAOCategoryIntegrationTest.java
rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/EmployeeDAOCategoryIntegrationTest.java
diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/categories/EmployeeDAOUnitTestSuite.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/EmployeeDAOUnitTestSuite.java
similarity index 100%
rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/categories/EmployeeDAOUnitTestSuite.java
rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/EmployeeDAOUnitTestSuite.java
diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/categories/IntegrationTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/IntegrationTest.java
similarity index 100%
rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/categories/IntegrationTest.java
rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/IntegrationTest.java
diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/categories/UnitTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/UnitTest.java
similarity index 100%
rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/categories/UnitTest.java
rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/categories/UnitTest.java
diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/example/EmployeeDAOIntegrationTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/example/EmployeeDAOIntegrationTest.java
similarity index 100%
rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/example/EmployeeDAOIntegrationTest.java
rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/example/EmployeeDAOIntegrationTest.java
diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/example/EmployeeUnitTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/example/EmployeeUnitTest.java
similarity index 100%
rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/example/EmployeeUnitTest.java
rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/example/EmployeeUnitTest.java
diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/resourcedirectory/ReadResourceDirectoryUnitTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/resourcedirectory/ReadResourceDirectoryUnitTest.java
similarity index 100%
rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/resourcedirectory/ReadResourceDirectoryUnitTest.java
rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/resourcedirectory/ReadResourceDirectoryUnitTest.java
diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/tags/EmployeeDAOIntegrationTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/tags/EmployeeDAOIntegrationTest.java
similarity index 100%
rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/tags/EmployeeDAOIntegrationTest.java
rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/tags/EmployeeDAOIntegrationTest.java
diff --git a/testing-modules/junit-5-configuration/src/test/java/com/baeldung/tags/EmployeeDAOTestSuite.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/tags/EmployeeDAOTestSuite.java
similarity index 100%
rename from testing-modules/junit-5-configuration/src/test/java/com/baeldung/tags/EmployeeDAOTestSuite.java
rename to testing-modules/junit-5-basics/src/test/java/com/baeldung/tags/EmployeeDAOTestSuite.java
diff --git a/testing-modules/junit-5-configuration/src/test/resources/example_resource.txt b/testing-modules/junit-5-basics/src/test/resources/example_resource.txt
similarity index 100%
rename from testing-modules/junit-5-configuration/src/test/resources/example_resource.txt
rename to testing-modules/junit-5-basics/src/test/resources/example_resource.txt
diff --git a/testing-modules/junit-5-configuration/README.md b/testing-modules/junit-5-configuration/README.md
deleted file mode 100644
index c274391766..0000000000
--- a/testing-modules/junit-5-configuration/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-### Relevant Articles:
--
diff --git a/testing-modules/junit-5/README.md b/testing-modules/junit-5/README.md
index aafdd75e81..47db6587b4 100644
--- a/testing-modules/junit-5/README.md
+++ b/testing-modules/junit-5/README.md
@@ -6,7 +6,7 @@
- [A Guide to JUnit 5 Extensions](http://www.baeldung.com/junit-5-extensions)
- [Inject Parameters into JUnit Jupiter Unit Tests](http://www.baeldung.com/junit-5-parameters)
- [Mockito and JUnit 5 – Using ExtendWith](http://www.baeldung.com/mockito-junit-5-extension)
-- [JUnit 5 @RunWith](http://www.baeldung.com/junit-5-runwith)
+- [JUnit5 @RunWith](http://www.baeldung.com/junit-5-runwith)
- [JUnit 5 @Test Annotation](http://www.baeldung.com/junit-5-test-annotation)
- [Assert an Exception is Thrown in JUnit 4 and 5](http://www.baeldung.com/junit-assert-exception)
- [@Before vs @BeforeClass vs @BeforeEach vs @BeforeAll](http://www.baeldung.com/junit-before-beforeclass-beforeeach-beforeall)
diff --git a/testing-modules/junit-5/pom.xml b/testing-modules/junit-5/pom.xml
index f27630a76d..84e0577cfe 100644
--- a/testing-modules/junit-5/pom.xml
+++ b/testing-modules/junit-5/pom.xml
@@ -21,24 +21,34 @@
junit-platform-engine
${junit.platform.version}
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit.jupiter.version}
+
org.junit.jupiter
junit-jupiter-params
${junit.jupiter.version}
+
+ org.junit.jupiter
+ junit-jupiter-api
+ ${junit.jupiter.version}
+
org.junit.platform
junit-platform-runner
${junit.platform.version}
test
-
+
org.junit.vintage
junit-vintage-engine
${junit.vintage.version}
test
-
+
org.junit.jupiter
junit-jupiter-migrationsupport
${junit.vintage.version}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/AssertionUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/AssertionUnitTest.java
index 31b6e14d6c..f1f7c531f2 100644
--- a/testing-modules/junit-5/src/test/java/com/baeldung/AssertionUnitTest.java
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/AssertionUnitTest.java
@@ -2,7 +2,21 @@ package com.baeldung;
import static java.time.Duration.ofSeconds;
import static java.util.Arrays.asList;
-import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertIterableEquals;
+import static org.junit.jupiter.api.Assertions.assertLinesMatch;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTimeout;
+import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
import java.util.ArrayList;
import java.util.LinkedList;
@@ -91,11 +105,12 @@ public class AssertionUnitTest {
@Test
public void givenMultipleAssertion_whenAssertingAll_thenOK() {
+ Object obj = null;
assertAll(
"heading",
() -> assertEquals(4, 2 * 2, "4 is 2 times 2"),
() -> assertEquals("java", "JAVA".toLowerCase()),
- () -> assertEquals(null, null, "null is equal to null")
+ () -> assertEquals(obj, null, "null is equal to null")
);
}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/AlphanumericOrderUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/AlphanumericOrderUnitTest.java
new file mode 100644
index 0000000000..d62ca0c666
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/AlphanumericOrderUnitTest.java
@@ -0,0 +1,33 @@
+package com.baeldung.junit5.order;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.MethodOrderer.Alphanumeric;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+
+@TestMethodOrder(Alphanumeric.class)
+public class AlphanumericOrderUnitTest {
+ private static StringBuilder output = new StringBuilder("");
+
+ @Test
+ public void myATest() {
+ output.append("A");
+ }
+
+ @Test
+ public void myBTest() {
+ output.append("B");
+ }
+
+ @Test
+ public void myaTest() {
+ output.append("a");
+ }
+
+ @AfterAll
+ public static void assertOutput() {
+ assertEquals(output.toString(), "ABa");
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/CustomOrder.java b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/CustomOrder.java
new file mode 100644
index 0000000000..e76230de63
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/CustomOrder.java
@@ -0,0 +1,12 @@
+package com.baeldung.junit5.order;
+
+import org.junit.jupiter.api.MethodDescriptor;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.MethodOrdererContext;
+
+public class CustomOrder implements MethodOrderer{
+ @Override
+ public void orderMethods(MethodOrdererContext context) {
+ context.getMethodDescriptors().sort((MethodDescriptor m1, MethodDescriptor m2)->m1.getMethod().getName().compareToIgnoreCase(m2.getMethod().getName()));
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/CustomOrderUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/CustomOrderUnitTest.java
new file mode 100644
index 0000000000..fa45921879
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/CustomOrderUnitTest.java
@@ -0,0 +1,33 @@
+package com.baeldung.junit5.order;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+
+@TestMethodOrder(CustomOrder.class)
+public class CustomOrderUnitTest {
+ private static StringBuilder output = new StringBuilder("");
+
+ @Test
+ public void myATest() {
+ output.append("A");
+ }
+
+ @Test
+ public void myBTest() {
+ output.append("B");
+ }
+
+ @Test
+ public void myaTest() {
+ output.append("a");
+ }
+
+
+ @AfterAll
+ public static void assertOutput() {
+ assertEquals(output.toString(), "AaB");
+ }
+}
diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/OrderAnnotationUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/OrderAnnotationUnitTest.java
new file mode 100644
index 0000000000..3d931a4158
--- /dev/null
+++ b/testing-modules/junit-5/src/test/java/com/baeldung/junit5/order/OrderAnnotationUnitTest.java
@@ -0,0 +1,37 @@
+package com.baeldung.junit5.order;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+
+@TestMethodOrder(OrderAnnotation.class)
+public class OrderAnnotationUnitTest {
+ private static StringBuilder output = new StringBuilder("");
+
+ @Test
+ @Order(1)
+ public void firstTest() {
+ output.append("a");
+ }
+
+ @Test
+ @Order(2)
+ public void secondTest() {
+ output.append("b");
+ }
+
+ @Test
+ @Order(3)
+ public void thirdTest() {
+ output.append("c");
+ }
+
+ @AfterAll
+ public static void assertOutput() {
+ assertEquals(output.toString(), "abc");
+ }
+}
diff --git a/testing-modules/mockito-2/README.md b/testing-modules/mockito-2/README.md
index ee443df81a..5c9e8fc81a 100644
--- a/testing-modules/mockito-2/README.md
+++ b/testing-modules/mockito-2/README.md
@@ -2,7 +2,4 @@
- [Mockito’s Java 8 Features](http://www.baeldung.com/mockito-2-java-8)
- [Lazy Verification with Mockito 2](http://www.baeldung.com/mockito-2-lazy-verification)
-
-## Mockito 2 and Java 8 Tips
-
-Examples on how to leverage Java 8 new features with Mockito version 2
+- [Mockito Strict Stubbing and The UnnecessaryStubbingException](https://www.baeldung.com/mockito-unnecessary-stubbing-exception)
diff --git a/testing-modules/pom.xml b/testing-modules/pom.xml
index 40ed63bc12..90ec857b7f 100644
--- a/testing-modules/pom.xml
+++ b/testing-modules/pom.xml
@@ -32,6 +32,6 @@
test-containers
testing
testng
- junit-5-configuration
+ junit-5-basics
diff --git a/testing-modules/rest-assured/README.md b/testing-modules/rest-assured/README.md
index d44fd08335..ec108353a0 100644
--- a/testing-modules/rest-assured/README.md
+++ b/testing-modules/rest-assured/README.md
@@ -2,3 +2,4 @@
- [A Guide to REST-assured](http://www.baeldung.com/rest-assured-tutorial)
- [REST-assured Support for Spring MockMvc](https://www.baeldung.com/spring-mock-mvc-rest-assured)
- [Getting and Verifying Response Data with REST-assured](https://www.baeldung.com/rest-assured-response)
+- [REST Assured Authentication](https://www.baeldung.com/rest-assured-authentication)