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 - 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)