diff --git a/.travis.yml b/.travis.yml index 683422dc97..5e86714a89 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ before_install: - echo "MAVEN_OPTS='-Xmx2048M -Xss128M -XX:+CMSClassUnloadingEnabled -XX:+UseG1GC -XX:-UseGCOverheadLimit'" > ~/.mavenrc install: skip -script: travis_wait 60 mvn -q install -Pdefault-first,default-second +script: travis_wait 60 mvn -q install -Pdefault-first,default-second -Dgib.enabled=true sudo: required diff --git a/algorithms-miscellaneous-2/README.md b/algorithms-miscellaneous-2/README.md index 6772a94a8d..d693a44f66 100644 --- a/algorithms-miscellaneous-2/README.md +++ b/algorithms-miscellaneous-2/README.md @@ -17,3 +17,4 @@ - [Round Up to the Nearest Hundred](https://www.baeldung.com/java-round-up-nearest-hundred) - [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) diff --git a/core-java-10/README.md b/core-java-10/README.md index 84fa381a26..f0a25712a7 100644 --- a/core-java-10/README.md +++ b/core-java-10/README.md @@ -4,3 +4,4 @@ - [Java 10 LocalVariable Type-Inference](http://www.baeldung.com/java-10-local-variable-type-inference) - [Guide to Java 10](http://www.baeldung.com/java-10-overview) - [Copy a List to Another List in Java](http://www.baeldung.com/java-copy-list-to-another) +- [Deep Dive Into the New Java JIT Compiler – Graal](https://www.baeldung.com/graal-java-jit-compiler) diff --git a/core-java-8/README.md b/core-java-8/README.md index ffd629a170..6786b29120 100644 --- a/core-java-8/README.md +++ b/core-java-8/README.md @@ -33,3 +33,4 @@ - [An Overview of Regular Expressions Performance in Java](https://www.baeldung.com/java-regex-performance) - [Java Primitives versus Objects](https://www.baeldung.com/java-primitives-vs-objects) - [How to Use if/else Logic in Java 8 Streams](https://www.baeldung.com/java-8-streams-if-else-logic) +- [How to Replace Many if Statements in Java](https://www.baeldung.com/java-replace-if-statements) diff --git a/core-java-arrays/src/main/java/com/baeldung/array/operations/ArrayOperations.java b/core-java-arrays/src/main/java/com/baeldung/array/operations/ArrayOperations.java index 98155ed952..d8cc0afd61 100644 --- a/core-java-arrays/src/main/java/com/baeldung/array/operations/ArrayOperations.java +++ b/core-java-arrays/src/main/java/com/baeldung/array/operations/ArrayOperations.java @@ -4,11 +4,13 @@ import java.lang.reflect.Array; import java.util.Arrays; import java.util.HashSet; import java.util.LinkedHashSet; +import java.util.LinkedList; import java.util.Random; import java.util.Set; import java.util.function.Function; import java.util.function.IntPredicate; import java.util.function.Predicate; +import java.util.stream.Stream; import org.apache.commons.lang3.ArrayUtils; @@ -194,4 +196,16 @@ public class ArrayOperations { public static T getRandomFromObjectArray(T[] array) { return array[new Random().nextInt(array.length)]; } + + public static Integer[] intersectionSimple(final Integer[] a, final Integer[] b){ + return Stream.of(a).filter(Arrays.asList(b)::contains).toArray(Integer[]::new); + } + + public static Integer[] intersectionSet(final Integer[] a, final Integer[] b){ + return Stream.of(a).filter(Arrays.asList(b)::contains).distinct().toArray(Integer[]::new); + } + + public static Integer[] intersectionMultiSet(final Integer[] a, final Integer[] b){ + return Stream.of(a).filter(new LinkedList<>(Arrays.asList(b))::remove).toArray(Integer[]::new); + } } diff --git a/core-java-arrays/src/test/java/com/baeldung/array/operations/IntersectionUnitTest.java b/core-java-arrays/src/test/java/com/baeldung/array/operations/IntersectionUnitTest.java new file mode 100644 index 0000000000..3c61060ea8 --- /dev/null +++ b/core-java-arrays/src/test/java/com/baeldung/array/operations/IntersectionUnitTest.java @@ -0,0 +1,66 @@ +package com.baeldung.array.operations; + +import org.junit.jupiter.api.Test; + +import static com.baeldung.array.operations.ArrayOperations.intersectionMultiSet; +import static com.baeldung.array.operations.ArrayOperations.intersectionSet; +import static com.baeldung.array.operations.ArrayOperations.intersectionSimple; +import static org.assertj.core.api.Assertions.assertThat; + +class IntersectionUnitTest { + private static final Integer[] a = { 1, 3, 2 }; + private static final Integer[] b = { 4, 3, 2, 4, 2, 3, 4, 4, 3 }; + private static final Integer[] c = { 1, 3, 2, 3, 3, 2 }; + + @Test + void whenIntersectionSimpleIsUsed_thenCommonEntriesAreInTheResult() { + assertThat(intersectionSimple(a, b)).isEqualTo(new Integer[] { 3, 2 }); + assertThat(intersectionSimple(b, a)).isEqualTo(new Integer[] { 3, 2, 2, 3, 3 }); + } + + @Test + void whenIntersectionSimpleIsUsedWithAnArrayAndItself_thenTheResultIsTheIdentity() { + assertThat(intersectionSimple(b, b)).isEqualTo(b); + assertThat(intersectionSimple(a, a)).isEqualTo(a); + } + + @Test + void whenIntersectionSetIsUsed_thenCommonEntriesAreInTheResult() { + assertThat(intersectionSet(b, a)).isEqualTo(new Integer[] { 3, 2 }); + } + + @Test + void whenIntersectionSetIsUsed_thenTheNumberOfEntriesDoesNotChangeWithTheParameterOrder() { + assertThat(intersectionSet(a, b)).isEqualTo(new Integer[] { 3, 2 }); + assertThat(intersectionSet(b, a)).isEqualTo(new Integer[] { 3, 2 }); + } + + @Test + void whenIntersectionSetIsUsedWithAnArrayAndWithItself_andTheInputHasNoDuplicateEntries_ThenTheResultIsTheIdentity() { + assertThat(intersectionSet(a, a)).isEqualTo(a); + } + + @Test + void whenIntersectionSetIsUsedWithAnArrayAndWithItself_andTheInputHasDuplicateEntries_ThenTheResultIsNotTheIdentity() { + assertThat(intersectionSet(b, b)).isNotEqualTo(b); + } + + @Test + void whenMultiSetIsUsed_thenCommonEntriesAreInTheResult() { + assertThat(intersectionMultiSet(b, a)).isEqualTo(new Integer[] { 3, 2 }); + } + + @Test + void whenIntersectionMultiSetIsUsed_thenTheNumberOfEntriesDoesNotChangeWithTheParameterOrder() { + assertThat(intersectionMultiSet(a, b)).isEqualTo(new Integer[] { 3, 2 }); + assertThat(intersectionMultiSet(b, a)).isEqualTo(new Integer[] { 3, 2 }); + assertThat(intersectionMultiSet(b, c)).isEqualTo(new Integer[] { 3, 2, 2, 3, 3 }); + assertThat(intersectionMultiSet(c, b)).isEqualTo(new Integer[] { 3, 2, 3, 3, 2 }); + } + + @Test + void whenIntersectionMultiSetIsUsedWithAnArrayAndWithItself_ThenTheResultIsTheIdentity() { + assertThat(intersectionMultiSet(b, b)).isEqualTo(b); + assertThat(intersectionMultiSet(a, a)).isEqualTo(a); + } +} \ No newline at end of file diff --git a/core-java-collections/README.md b/core-java-collections/README.md index fbc8144954..858dbef0b3 100644 --- a/core-java-collections/README.md +++ b/core-java-collections/README.md @@ -43,3 +43,11 @@ - [Converting a Collection to ArrayList in Java](https://www.baeldung.com/java-convert-collection-arraylist) - [Java 8 Streams: Find Items From One List Based On Values From Another List](https://www.baeldung.com/java-streams-find-list-items) - [Combining Different Types of Collections in Java](https://www.baeldung.com/java-combine-collections) +- [Sorting in Java](http://www.baeldung.com/java-sorting) +- [A Guide to the Java LinkedList](http://www.baeldung.com/java-linkedlist) +- [Java List UnsupportedOperationException](http://www.baeldung.com/java-list-unsupported-operation-exception) +- [Join and Split Arrays and Collections in Java](http://www.baeldung.com/java-join-and-split) +- [Check If Two Lists are Equal in Java](http://www.baeldung.com/java-test-a-list-for-ordinality-and-equality) +- [Java List Initialization in One Line](https://www.baeldung.com/java-init-list-one-line) +- [ClassCastException: Arrays$ArrayList cannot be cast to ArrayList](https://www.baeldung.com/java-classcastexception-arrays-arraylist) +- [A Guide to EnumMap](https://www.baeldung.com/java-enum-map) diff --git a/core-java-collections/pom.xml b/core-java-collections/pom.xml index 31f0d7419f..2201ee8b15 100644 --- a/core-java-collections/pom.xml +++ b/core-java-collections/pom.xml @@ -56,6 +56,12 @@ commons-exec 1.3 + + org.projectlombok + lombok + ${lombok.version} + provided + @@ -67,5 +73,6 @@ 1.7.0 3.11.1 7.1.0 + 1.16.12 diff --git a/core-java/src/main/java/com/baeldung/classcastexception/ClassCastException.java b/core-java-collections/src/main/java/com/baeldung/classcastexception/ClassCastException.java similarity index 100% rename from core-java/src/main/java/com/baeldung/classcastexception/ClassCastException.java rename to core-java-collections/src/main/java/com/baeldung/classcastexception/ClassCastException.java diff --git a/core-java/src/test/java/com/baeldung/java/listInitialization/ListInitializationUnitTest.java b/core-java-collections/src/test/java/com/baeldung/java/listInitialization/ListInitializationUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/java/listInitialization/ListInitializationUnitTest.java rename to core-java-collections/src/test/java/com/baeldung/java/listInitialization/ListInitializationUnitTest.java diff --git a/core-java/src/test/java/org/baeldung/java/sorting/Employee.java b/core-java-collections/src/test/java/org/baeldung/java/sorting/Employee.java similarity index 100% rename from core-java/src/test/java/org/baeldung/java/sorting/Employee.java rename to core-java-collections/src/test/java/org/baeldung/java/sorting/Employee.java diff --git a/core-java/src/test/java/org/baeldung/java/sorting/JavaSortingUnitTest.java b/core-java-collections/src/test/java/org/baeldung/java/sorting/JavaSortingUnitTest.java similarity index 100% rename from core-java/src/test/java/org/baeldung/java/sorting/JavaSortingUnitTest.java rename to core-java-collections/src/test/java/org/baeldung/java/sorting/JavaSortingUnitTest.java diff --git a/core-java-io/README.md b/core-java-io/README.md index c81e466b57..3d028783ed 100644 --- a/core-java-io/README.md +++ b/core-java-io/README.md @@ -34,3 +34,4 @@ - [Read a File into an ArrayList](https://www.baeldung.com/java-file-to-arraylist) - [Guide to Java OutputStream](https://www.baeldung.com/java-outputstream) - [Reading a CSV File into an Array](https://www.baeldung.com/java-csv-file-array) +- [Guide to BufferedReader](https://www.baeldung.com/java-buffered-reader) diff --git a/core-java-lang/README.md b/core-java-lang/README.md index 85312cba68..62af72818f 100644 --- a/core-java-lang/README.md +++ b/core-java-lang/README.md @@ -56,4 +56,5 @@ - [How to Separate Double into Integer and Decimal Parts](https://www.baeldung.com/java-separate-double-into-integer-decimal-parts) - [“Sneaky Throws” in Java](http://www.baeldung.com/java-sneaky-throws) - [Inheritance and Composition (Is-a vs Has-a relationship) in Java](http://www.baeldung.com/java-inheritance-composition) +- [A Guide to Constructors in Java](https://www.baeldung.com/java-constructors) diff --git a/core-java-lang/src/main/java/com/baeldung/constructors/BankAccount.java b/core-java-lang/src/main/java/com/baeldung/constructors/BankAccount.java new file mode 100644 index 0000000000..3d50e85245 --- /dev/null +++ b/core-java-lang/src/main/java/com/baeldung/constructors/BankAccount.java @@ -0,0 +1,56 @@ +package com.baeldung.constructors; + +import java.time.LocalDateTime; + +class BankAccount { + String name; + LocalDateTime opened; + double balance; + + @Override + public String toString() { + return String.format("%s, %s, %f", this.name, this.opened.toString(), this.balance); + } + + public String getName() { + return name; + } + + public LocalDateTime getOpened() { + return opened; + } + + public double getBalance() { + return this.balance; + } +} + +class BankAccountEmptyConstructor extends BankAccount { + public BankAccountEmptyConstructor() { + this.name = ""; + this.opened = LocalDateTime.now(); + this.balance = 0.0d; + } +} + +class BankAccountParameterizedConstructor extends BankAccount { + public BankAccountParameterizedConstructor(String name, LocalDateTime opened, double balance) { + this.name = name; + this.opened = opened; + this.balance = balance; + } +} + +class BankAccountCopyConstructor extends BankAccount { + public BankAccountCopyConstructor(String name, LocalDateTime opened, double balance) { + this.name = name; + this.opened = opened; + this.balance = balance; + } + + public BankAccountCopyConstructor(BankAccount other) { + this.name = other.name; + this.opened = LocalDateTime.now(); + this.balance = 0.0f; + } +} diff --git a/core-java-lang/src/main/java/com/baeldung/constructors/Transaction.java b/core-java-lang/src/main/java/com/baeldung/constructors/Transaction.java new file mode 100644 index 0000000000..14704f507a --- /dev/null +++ b/core-java-lang/src/main/java/com/baeldung/constructors/Transaction.java @@ -0,0 +1,25 @@ +package com.baeldung.constructors; + +import java.time.LocalDateTime; + +class Transaction { + final BankAccountEmptyConstructor bankAccount; + final LocalDateTime date; + final double amount; + + public Transaction(BankAccountEmptyConstructor account, LocalDateTime date, double amount) { + this.bankAccount = account; + this.date = date; + this.amount = amount; + } + + /* + * Compilation Error :'(, all final variables must be explicitly initialised. + * public Transaction() { + * } + */ + + public void invalidMethod() { + // this.amount = 102.03; // Results in a compiler error. You cannot change the value of a final variable. + } +} diff --git a/core-java-lang/src/test/java/com/baeldung/constructors/ConstructorUnitTest.java b/core-java-lang/src/test/java/com/baeldung/constructors/ConstructorUnitTest.java new file mode 100644 index 0000000000..2cd8832fbf --- /dev/null +++ b/core-java-lang/src/test/java/com/baeldung/constructors/ConstructorUnitTest.java @@ -0,0 +1,53 @@ +package com.baeldung.constructors; + +import com.baeldung.constructors.*; + +import java.util.logging.Logger; +import java.time.LocalDateTime; +import java.time.Month; + +import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class ConstructorUnitTest { + final static Logger LOGGER = Logger.getLogger(ConstructorUnitTest.class.getName()); + + @Test + public void givenNoExplicitContructor_whenUsed_thenFails() { + BankAccount account = new BankAccount(); + assertThatThrownBy(() -> { account.toString(); }).isInstanceOf(Exception.class); + } + + @Test + public void givenNoArgumentConstructor_whenUsed_thenSucceeds() { + BankAccountEmptyConstructor account = new BankAccountEmptyConstructor(); + assertThatCode(() -> { + account.toString(); + }).doesNotThrowAnyException(); + } + + @Test + public void givenParameterisedConstructor_whenUsed_thenSucceeds() { + LocalDateTime opened = LocalDateTime.of(2018, Month.JUNE, 29, 06, 30, 00); + BankAccountParameterizedConstructor account = + new BankAccountParameterizedConstructor("Tom", opened, 1000.0f); + + assertThatCode(() -> { + account.toString(); + }).doesNotThrowAnyException(); + } + + @Test + public void givenCopyContructor_whenUser_thenMaintainsLogic() { + LocalDateTime opened = LocalDateTime.of(2018, Month.JUNE, 29, 06, 30, 00); + BankAccountCopyConstructor account = new BankAccountCopyConstructor("Tim", opened, 1000.0f); + BankAccountCopyConstructor newAccount = new BankAccountCopyConstructor(account); + + assertThat(account.getName()).isEqualTo(newAccount.getName()); + assertThat(account.getOpened()).isNotEqualTo(newAccount.getOpened()); + + assertThat(newAccount.getBalance()).isEqualTo(0.0f); + } +} diff --git a/core-java/README.md b/core-java/README.md index 2be137add6..e8923e9a2f 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -10,7 +10,6 @@ - [Guide to the Fork/Join Framework in Java](http://www.baeldung.com/java-fork-join) - [How to Print Screen in Java](http://www.baeldung.com/print-screen-in-java) - [A Guide To Java Regular Expressions API](http://www.baeldung.com/regular-expressions-java) -- [Sorting in Java](http://www.baeldung.com/java-sorting) - [Getting Started with Java Properties](http://www.baeldung.com/java-properties) - [Pattern Search with Grep in Java](http://www.baeldung.com/grep-in-java) - [URL Encoding and Decoding in Java](http://www.baeldung.com/java-url-encoding-decoding) @@ -39,7 +38,6 @@ - [Quick Guide to Java Stack](http://www.baeldung.com/java-stack) - [Guide to java.util.Formatter](http://www.baeldung.com/java-string-formatter) - [Guide to the Cipher Class](http://www.baeldung.com/java-cipher-class) -- [Implementing a Binary Tree in Java](http://www.baeldung.com/java-binary-tree) - [A Guide to ThreadLocalRandom in Java](http://www.baeldung.com/java-thread-local-random) - [Compiling Java *.class Files with javac](http://www.baeldung.com/javac) - [A Guide to Iterator in Java](http://www.baeldung.com/java-iterator) @@ -49,15 +47,10 @@ - [A Practical Guide to DecimalFormat](http://www.baeldung.com/java-decimalformat) - [How to Detect the OS Using Java](http://www.baeldung.com/java-detect-os) - [ASCII Art in Java](http://www.baeldung.com/ascii-art-in-java) -- [Finding Max/Min of a List or Collection](http://www.baeldung.com/java-collection-min-max) - [What is the serialVersionUID?](http://www.baeldung.com/java-serial-version-uid) - [A Guide To UDP In Java](http://www.baeldung.com/udp-in-java) -- [A Guide to the Java LinkedList](http://www.baeldung.com/java-linkedlist) - [A Guide to the ResourceBundle](http://www.baeldung.com/java-resourcebundle) - [Class Loaders in Java](http://www.baeldung.com/java-classloaders) -- [Java List UnsupportedOperationException](http://www.baeldung.com/java-list-unsupported-operation-exception) -- [Join and Split Arrays and Collections in Java](http://www.baeldung.com/java-join-and-split) -- [Check If Two Lists are Equal in Java](http://www.baeldung.com/java-test-a-list-for-ordinality-and-equality) - [Sending Emails with Java](http://www.baeldung.com/java-email) - [Introduction to SSL in Java](http://www.baeldung.com/java-ssl) - [Java KeyStore API](http://www.baeldung.com/java-keystore) @@ -80,8 +73,6 @@ - [Getting a File’s Mime Type in Java](http://www.baeldung.com/java-file-mime-type) - [Common Java Exceptions](http://www.baeldung.com/java-common-exceptions) - [Java Constructors vs Static Factory Methods](https://www.baeldung.com/java-constructors-vs-static-factory-methods) -- [Java List Initialization in One Line](https://www.baeldung.com/java-init-list-one-line) -- [ClassCastException: Arrays$ArrayList cannot be cast to ArrayList](https://www.baeldung.com/java-classcastexception-arrays-arraylist) - [Throw Exception in Optional in Java 8](https://www.baeldung.com/java-optional-throw-exception) - [Add a Character to a String at a Given Position](https://www.baeldung.com/java-add-character-to-string) - [Calculating the nth Root in Java](https://www.baeldung.com/java-nth-root) @@ -93,3 +84,7 @@ - [Understanding Memory Leaks in Java](https://www.baeldung.com/java-memory-leaks) - [A Guide to SimpleDateFormat](https://www.baeldung.com/java-simple-date-format) - [SSL Handshake Failures](https://www.baeldung.com/java-ssl-handshake-failures) +- [Implementing a Binary Tree in Java](https://www.baeldung.com/java-binary-tree) +- [Changing the Order in a Sum Operation Can Produce Different Results?](https://www.baeldung.com/java-floating-point-sum-order) +- [Java – Try with Resources](https://www.baeldung.com/java-try-with-resources) +- [Abstract Classes in Java](https://www.baeldung.com/java-abstract-class) diff --git a/core-java/src/main/java/com/baeldung/abstractclasses/application/Application.java b/core-java/src/main/java/com/baeldung/abstractclasses/application/Application.java index fe30c66484..3180762227 100644 --- a/core-java/src/main/java/com/baeldung/abstractclasses/application/Application.java +++ b/core-java/src/main/java/com/baeldung/abstractclasses/application/Application.java @@ -2,29 +2,28 @@ package com.baeldung.abstractclasses.application; import com.baeldung.abstractclasses.filereaders.BaseFileReader; import com.baeldung.abstractclasses.filereaders.LowercaseFileReader; -import com.baeldung.abstractclasses.filereaders.StandardFileReader; import com.baeldung.abstractclasses.filereaders.UppercaseFileReader; import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.nio.file.Paths; public class Application { - public static void main(String[] args) throws IOException { - + public static void main(String[] args) throws IOException, URISyntaxException { + Application application = new Application(); - String filePath = application.getFilePathFromResourcesFolder("files/test.txt"); - - BaseFileReader lowercaseFileReader = new LowercaseFileReader(filePath); + Path path = application.getPathFromResourcesFile("files/test.txt"); + BaseFileReader lowercaseFileReader = new LowercaseFileReader(path); lowercaseFileReader.readFile().forEach(line -> System.out.println(line)); + + BaseFileReader uppercaseFileReader = new UppercaseFileReader(path); + uppercaseFileReader.readFile().forEach(line -> System.out.println(line)); - BaseFileReader upperCaseFileReader = new UppercaseFileReader(filePath); - upperCaseFileReader.readFile().forEach(line -> System.out.println(line)); - - BaseFileReader standardFileReader = new StandardFileReader(filePath); - standardFileReader.readFile().forEach(line -> System.out.println(line)); - } - private String getFilePathFromResourcesFolder(String fileName) { - return getClass().getClassLoader().getResource(fileName).getPath().substring(1); + private Path getPathFromResourcesFile(String filePath) throws URISyntaxException { + return Paths.get(getClass().getClassLoader().getResource(filePath).toURI()); + } } diff --git a/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/BaseFileReader.java b/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/BaseFileReader.java index 659913f046..97452a9eca 100644 --- a/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/BaseFileReader.java +++ b/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/BaseFileReader.java @@ -1,19 +1,27 @@ package com.baeldung.abstractclasses.filereaders; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.List; +import java.util.stream.Collectors; public abstract class BaseFileReader { - protected String filePath; + protected Path filePath; - protected BaseFileReader(String filePath) { + protected BaseFileReader(Path filePath) { this.filePath = filePath; } - public String getFilePath() { + public Path getFilePath() { return filePath; } - public abstract List readFile() throws IOException; + public List readFile() throws IOException { + return Files.lines(filePath) + .map(this::mapFileLine).collect(Collectors.toList()); + } + + protected abstract String mapFileLine(String line); } diff --git a/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/LowercaseFileReader.java b/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/LowercaseFileReader.java index 0bbef45eb8..53820d393c 100644 --- a/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/LowercaseFileReader.java +++ b/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/LowercaseFileReader.java @@ -1,21 +1,15 @@ package com.baeldung.abstractclasses.filereaders; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.List; -import java.util.stream.Collectors; +import java.nio.file.Path; public class LowercaseFileReader extends BaseFileReader { - public LowercaseFileReader(String filePath) { + public LowercaseFileReader(Path filePath) { super(filePath); } - + @Override - public List readFile() throws IOException { - return Files.lines(Paths.get(filePath)) - .map(String::toLowerCase) - .collect(Collectors.toList()); - } + public String mapFileLine(String line) { + return line.toLowerCase(); + } } diff --git a/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/StandardFileReader.java b/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/StandardFileReader.java deleted file mode 100644 index 0a90d53c38..0000000000 --- a/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/StandardFileReader.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.baeldung.abstractclasses.filereaders; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.List; -import java.util.stream.Collectors; - -public class StandardFileReader extends BaseFileReader { - - public StandardFileReader(String filePath) { - super(filePath); - } - - @Override - public List readFile() throws IOException { - return Files.lines(Paths.get(filePath)).collect(Collectors.toList()); - } -} diff --git a/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/UppercaseFileReader.java b/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/UppercaseFileReader.java index 4e8f150964..3144a4f27f 100644 --- a/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/UppercaseFileReader.java +++ b/core-java/src/main/java/com/baeldung/abstractclasses/filereaders/UppercaseFileReader.java @@ -1,21 +1,15 @@ package com.baeldung.abstractclasses.filereaders; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.List; -import java.util.stream.Collectors; +import java.nio.file.Path; public class UppercaseFileReader extends BaseFileReader { - - public UppercaseFileReader(String filePath) { + + public UppercaseFileReader(Path filePath) { super(filePath); } - + @Override - public List readFile() throws IOException { - return Files.lines(Paths.get(filePath)) - .map(String::toUpperCase) - .collect(Collectors.toList()); + public String mapFileLine(String line) { + return line.toUpperCase(); } } diff --git a/core-java/src/main/java/com/baeldung/className/RetrievingClassName.java b/core-java/src/main/java/com/baeldung/className/RetrievingClassName.java new file mode 100644 index 0000000000..ab6c8a51ff --- /dev/null +++ b/core-java/src/main/java/com/baeldung/className/RetrievingClassName.java @@ -0,0 +1,9 @@ +package com.baeldung.className; + +public class RetrievingClassName { + + public class InnerClass { + + } + +} diff --git a/core-java/src/main/java/com/baeldung/networking/proxies/CommandLineProxyDemo.java b/core-java/src/main/java/com/baeldung/networking/proxies/CommandLineProxyDemo.java new file mode 100644 index 0000000000..bbc8a81c98 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/networking/proxies/CommandLineProxyDemo.java @@ -0,0 +1,17 @@ +package com.baeldung.networking.proxies; + +import java.net.URL; +import java.net.URLConnection; + +public class CommandLineProxyDemo { + + public static final String RESOURCE_URL = "http://www.google.com"; + + public static void main(String[] args) throws Exception { + + URL url = new URL(RESOURCE_URL); + URLConnection con = url.openConnection(); + System.out.println(UrlConnectionUtils.contentAsString(con)); + } + +} \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/networking/proxies/DirectProxyDemo.java b/core-java/src/main/java/com/baeldung/networking/proxies/DirectProxyDemo.java new file mode 100644 index 0000000000..07a7880886 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/networking/proxies/DirectProxyDemo.java @@ -0,0 +1,20 @@ +package com.baeldung.networking.proxies; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.Proxy; +import java.net.URL; + +public class DirectProxyDemo { + + private static final String URL_STRING = "http://www.google.com"; + + public static void main(String... args) throws IOException { + + URL weburl = new URL(URL_STRING); + HttpURLConnection directConnection + = (HttpURLConnection) weburl.openConnection(Proxy.NO_PROXY); + System.out.println(UrlConnectionUtils.contentAsString(directConnection)); + } + +} diff --git a/core-java/src/main/java/com/baeldung/networking/proxies/SocksProxyDemo.java b/core-java/src/main/java/com/baeldung/networking/proxies/SocksProxyDemo.java new file mode 100644 index 0000000000..e7ac3c0264 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/networking/proxies/SocksProxyDemo.java @@ -0,0 +1,32 @@ +package com.baeldung.networking.proxies; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.Socket; +import java.net.URL; + +public class SocksProxyDemo { + + private static final String URL_STRING = "http://www.google.com"; + private static final String SOCKET_SERVER_HOST = "someserver.baeldung.com"; + private static final int SOCKET_SERVER_PORT = 1111; + + public static void main(String... args) throws IOException { + + URL weburl = new URL(URL_STRING); + Proxy socksProxy + = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", 1080)); + HttpURLConnection socksConnection + = (HttpURLConnection) weburl.openConnection(socksProxy); + System.out.println(UrlConnectionUtils.contentAsString(socksConnection)); + + Socket proxySocket = new Socket(socksProxy); + InetSocketAddress socketHost + = new InetSocketAddress(SOCKET_SERVER_HOST, SOCKET_SERVER_PORT); + proxySocket.connect(socketHost); + // do stuff with the socket + } + +} diff --git a/core-java/src/main/java/com/baeldung/networking/proxies/SystemPropertyProxyDemo.java b/core-java/src/main/java/com/baeldung/networking/proxies/SystemPropertyProxyDemo.java new file mode 100644 index 0000000000..1f589eac58 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/networking/proxies/SystemPropertyProxyDemo.java @@ -0,0 +1,23 @@ +package com.baeldung.networking.proxies; + +import java.net.URL; +import java.net.URLConnection; + +public class SystemPropertyProxyDemo { + + public static final String RESOURCE_URL = "http://www.google.com"; + + public static void main(String[] args) throws Exception { + + System.setProperty("http.proxyHost", "127.0.0.1"); + System.setProperty("http.proxyPort", "3128"); + + URL url = new URL(RESOURCE_URL); + URLConnection con = url.openConnection(); + System.out.println(UrlConnectionUtils.contentAsString(con)); + + System.setProperty("http.proxyHost", null); + // proxy will no longer be used for http connections + } + +} diff --git a/core-java/src/main/java/com/baeldung/networking/proxies/UrlConnectionUtils.java b/core-java/src/main/java/com/baeldung/networking/proxies/UrlConnectionUtils.java new file mode 100644 index 0000000000..aa12824a90 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/networking/proxies/UrlConnectionUtils.java @@ -0,0 +1,21 @@ +package com.baeldung.networking.proxies; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URLConnection; + +class UrlConnectionUtils { + + public static String contentAsString(URLConnection con) throws IOException { + StringBuilder builder = new StringBuilder(); + try (BufferedReader reader + = new BufferedReader(new InputStreamReader(con.getInputStream()))){ + while (reader.ready()) { + builder.append(reader.readLine()); + } + } + return builder.toString(); + } + +} diff --git a/core-java/src/main/java/com/baeldung/networking/proxies/WebProxyDemo.java b/core-java/src/main/java/com/baeldung/networking/proxies/WebProxyDemo.java new file mode 100644 index 0000000000..41caaf3439 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/networking/proxies/WebProxyDemo.java @@ -0,0 +1,23 @@ +package com.baeldung.networking.proxies; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.URL; + +public class WebProxyDemo { + + private static final String URL_STRING = "http://www.google.com"; + + public static void main(String... args) throws IOException { + + URL weburl = new URL(URL_STRING); + Proxy webProxy + = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 3128)); + HttpURLConnection webProxyConnection + = (HttpURLConnection) weburl.openConnection(webProxy); + System.out.println(UrlConnectionUtils.contentAsString(webProxyConnection)); + } + +} diff --git a/core-java/src/test/java/com/baeldung/abstractclasses/StandardFileReaderUnitTest.java b/core-java/src/test/java/com/baeldung/abstractclasses/StandardFileReaderUnitTest.java deleted file mode 100644 index 348b0f0366..0000000000 --- a/core-java/src/test/java/com/baeldung/abstractclasses/StandardFileReaderUnitTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.baeldung.abstractclasses; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.net.URL; -import java.nio.file.Paths; -import java.util.List; - -import org.junit.Test; - -import com.baeldung.abstractclasses.filereaders.BaseFileReader; -import com.baeldung.abstractclasses.filereaders.StandardFileReader; - -public class StandardFileReaderUnitTest { - - @Test - public void givenStandardFileReaderInstance_whenCalledreadFile_thenCorrect() throws Exception { - // We'll transform the resource URL path to URI to load the file correctly in Windows - URL url = getClass().getClassLoader().getResource("files/test.txt"); - String filePath = Paths.get(url.toURI()).toString(); - BaseFileReader standardFileReader = new StandardFileReader(filePath); - - assertThat(standardFileReader.readFile()).isInstanceOf(List.class); - } -} diff --git a/core-java/src/test/java/com/baeldung/abstractclasses/LowercaseFileReaderUnitTest.java b/core-java/src/test/java/com/baeldung/abstractclasses/test/LowercaseFileReaderUnitTest.java similarity index 63% rename from core-java/src/test/java/com/baeldung/abstractclasses/LowercaseFileReaderUnitTest.java rename to core-java/src/test/java/com/baeldung/abstractclasses/test/LowercaseFileReaderUnitTest.java index a97a68e0bd..4f0d3a7cd5 100644 --- a/core-java/src/test/java/com/baeldung/abstractclasses/LowercaseFileReaderUnitTest.java +++ b/core-java/src/test/java/com/baeldung/abstractclasses/test/LowercaseFileReaderUnitTest.java @@ -1,23 +1,20 @@ -package com.baeldung.abstractclasses; +package com.baeldung.abstractclasses.test; import com.baeldung.abstractclasses.filereaders.BaseFileReader; import com.baeldung.abstractclasses.filereaders.LowercaseFileReader; - -import java.net.URL; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import org.junit.Test; public class LowercaseFileReaderUnitTest { - + @Test public void givenLowercaseFileReaderInstance_whenCalledreadFile_thenCorrect() throws Exception { - // We'll transform the resource URL path to URI to load the file correctly in Windows - URL url = getClass().getClassLoader().getResource("files/test.txt"); - String filePath = Paths.get(url.toURI()).toString(); - BaseFileReader lowercaseFileReader = new LowercaseFileReader(filePath); - + Path path = Paths.get(getClass().getClassLoader().getResource("files/test.txt").toURI()); + BaseFileReader lowercaseFileReader = new LowercaseFileReader(path); + assertThat(lowercaseFileReader.readFile()).isInstanceOf(List.class); } } diff --git a/core-java/src/test/java/com/baeldung/abstractclasses/UppercaseFileReaderUnitTest.java b/core-java/src/test/java/com/baeldung/abstractclasses/test/UppercaseFileReaderUnitTest.java similarity index 62% rename from core-java/src/test/java/com/baeldung/abstractclasses/UppercaseFileReaderUnitTest.java rename to core-java/src/test/java/com/baeldung/abstractclasses/test/UppercaseFileReaderUnitTest.java index d698cfe038..e11db57000 100644 --- a/core-java/src/test/java/com/baeldung/abstractclasses/UppercaseFileReaderUnitTest.java +++ b/core-java/src/test/java/com/baeldung/abstractclasses/test/UppercaseFileReaderUnitTest.java @@ -1,9 +1,8 @@ -package com.baeldung.abstractclasses; +package com.baeldung.abstractclasses.test; import com.baeldung.abstractclasses.filereaders.BaseFileReader; import com.baeldung.abstractclasses.filereaders.UppercaseFileReader; - -import java.net.URL; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @@ -13,11 +12,9 @@ public class UppercaseFileReaderUnitTest { @Test public void givenUppercaseFileReaderInstance_whenCalledreadFile_thenCorrect() throws Exception { - // We'll transform the resource URL path to URI to load the file correctly in Windows - URL url = getClass().getClassLoader().getResource("files/test.txt"); - String filePath = Paths.get(url.toURI()).toString(); - BaseFileReader uppercaseFileReader = new UppercaseFileReader(filePath); + Path path = Paths.get(getClass().getClassLoader().getResource("files/test.txt").toURI()); + BaseFileReader uppercaseFileReader = new UppercaseFileReader(path); assertThat(uppercaseFileReader.readFile()).isInstanceOf(List.class); - } + } } diff --git a/core-java/src/test/java/com/baeldung/className/RetrievingClassNameUnitTest.java b/core-java/src/test/java/com/baeldung/className/RetrievingClassNameUnitTest.java new file mode 100644 index 0000000000..f9dbf91d2c --- /dev/null +++ b/core-java/src/test/java/com/baeldung/className/RetrievingClassNameUnitTest.java @@ -0,0 +1,156 @@ +package com.baeldung.className; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +public class RetrievingClassNameUnitTest { + + // Retrieving Simple Name + @Test + public void givenRetrievingClassName_whenGetSimpleName_thenRetrievingClassName() { + assertEquals("RetrievingClassName", RetrievingClassName.class.getSimpleName()); + } + + @Test + public void givenPrimitiveInt_whenGetSimpleName_thenInt() { + assertEquals("int", int.class.getSimpleName()); + } + + @Test + public void givenRetrievingClassNameArray_whenGetSimpleName_thenRetrievingClassNameWithBrackets() { + assertEquals("RetrievingClassName[]", RetrievingClassName[].class.getSimpleName()); + assertEquals("RetrievingClassName[][]", RetrievingClassName[][].class.getSimpleName()); + } + + @Test + public void givenAnonymousClass_whenGetSimpleName_thenEmptyString() { + assertEquals("", new RetrievingClassName() {}.getClass().getSimpleName()); + } + + // Retrieving Other Names + // - Primitive Types + @Test + public void givenPrimitiveInt_whenGetName_thenInt() { + assertEquals("int", int.class.getName()); + } + + @Test + public void givenPrimitiveInt_whenGetTypeName_thenInt() { + assertEquals("int", int.class.getTypeName()); + } + + @Test + public void givenPrimitiveInt_whenGetCanonicalName_thenInt() { + assertEquals("int", int.class.getCanonicalName()); + } + + // - Object Types + @Test + public void givenRetrievingClassName_whenGetName_thenCanonicalName() { + assertEquals("com.baeldung.className.RetrievingClassName", RetrievingClassName.class.getName()); + } + + @Test + public void givenRetrievingClassName_whenGetTypeName_thenCanonicalName() { + assertEquals("com.baeldung.className.RetrievingClassName", RetrievingClassName.class.getTypeName()); + } + + @Test + public void givenRetrievingClassName_whenGetCanonicalName_thenCanonicalName() { + assertEquals("com.baeldung.className.RetrievingClassName", RetrievingClassName.class.getCanonicalName()); + } + + // - Inner Classes + @Test + public void givenRetrievingClassNameInnerClass_whenGetName_thenCanonicalNameWithDollarSeparator() { + assertEquals("com.baeldung.className.RetrievingClassName$InnerClass", RetrievingClassName.InnerClass.class.getName()); + } + + @Test + public void givenRetrievingClassNameInnerClass_whenGetTypeName_thenCanonicalNameWithDollarSeparator() { + assertEquals("com.baeldung.className.RetrievingClassName$InnerClass", RetrievingClassName.InnerClass.class.getTypeName()); + } + + @Test + public void givenRetrievingClassNameInnerClass_whenGetCanonicalName_thenCanonicalName() { + assertEquals("com.baeldung.className.RetrievingClassName.InnerClass", RetrievingClassName.InnerClass.class.getCanonicalName()); + } + + // - Anonymous Classes + @Test + public void givenAnonymousClass_whenGetName_thenCallingClassCanonicalNameWithDollarSeparatorAndCountNumber() { + // These are the second and third appearences of an anonymous class in RetrievingClassNameUnitTest, hence $2 and $3 expectations + assertEquals("com.baeldung.className.RetrievingClassNameUnitTest$2", new RetrievingClassName() {}.getClass().getName()); + assertEquals("com.baeldung.className.RetrievingClassNameUnitTest$3", new RetrievingClassName() {}.getClass().getName()); + } + + @Test + public void givenAnonymousClass_whenGetTypeName_thenCallingClassCanonicalNameWithDollarSeparatorAndCountNumber() { + // These are the fourth and fifth appearences of an anonymous class in RetrievingClassNameUnitTest, hence $4 and $5 expectations + assertEquals("com.baeldung.className.RetrievingClassNameUnitTest$4", new RetrievingClassName() {}.getClass().getTypeName()); + assertEquals("com.baeldung.className.RetrievingClassNameUnitTest$5", new RetrievingClassName() {}.getClass().getTypeName()); + } + + @Test + public void givenAnonymousClass_whenGetCanonicalName_thenNull() { + assertNull(new RetrievingClassName() {}.getClass().getCanonicalName()); + } + + // - Arrays + @Test + public void givenPrimitiveIntArray_whenGetName_thenOpeningBracketsAndPrimitiveIntLetter() { + assertEquals("[I", int[].class.getName()); + assertEquals("[[I", int[][].class.getName()); + } + + @Test + public void givenRetrievingClassNameArray_whenGetName_thenOpeningBracketsLetterLAndRetrievingClassNameGetName() { + assertEquals("[Lcom.baeldung.className.RetrievingClassName;", RetrievingClassName[].class.getName()); + assertEquals("[[Lcom.baeldung.className.RetrievingClassName;", RetrievingClassName[][].class.getName()); + } + + @Test + public void givenRetrievingClassNameInnerClassArray_whenGetName_thenOpeningBracketsLetterLAndRetrievingClassNameInnerClassGetName() { + assertEquals("[Lcom.baeldung.className.RetrievingClassName$InnerClass;", RetrievingClassName.InnerClass[].class.getName()); + assertEquals("[[Lcom.baeldung.className.RetrievingClassName$InnerClass;", RetrievingClassName.InnerClass[][].class.getName()); + } + + @Test + public void givenPrimitiveIntArray_whenGetTypeName_thenPrimitiveIntGetTypeNameWithBrackets() { + assertEquals("int[]", int[].class.getTypeName()); + assertEquals("int[][]", int[][].class.getTypeName()); + } + + @Test + public void givenRetrievingClassNameArray_whenGetTypeName_thenRetrievingClassNameGetTypeNameWithBrackets() { + assertEquals("com.baeldung.className.RetrievingClassName[]", RetrievingClassName[].class.getTypeName()); + assertEquals("com.baeldung.className.RetrievingClassName[][]", RetrievingClassName[][].class.getTypeName()); + } + + @Test + public void givenRetrievingClassNameInnerClassArray_whenGetTypeName_thenRetrievingClassNameInnerClassGetTypeNameWithBrackets() { + assertEquals("com.baeldung.className.RetrievingClassName$InnerClass[]", RetrievingClassName.InnerClass[].class.getTypeName()); + assertEquals("com.baeldung.className.RetrievingClassName$InnerClass[][]", RetrievingClassName.InnerClass[][].class.getTypeName()); + } + + @Test + public void givenPrimitiveIntArray_whenGetCanonicalName_thenPrimitiveIntGetCanonicalNameWithBrackets() { + assertEquals("int[]", int[].class.getCanonicalName()); + assertEquals("int[][]", int[][].class.getCanonicalName()); + } + + @Test + public void givenRetrievingClassNameArray_whenGetCanonicalName_thenRetrievingClassNameGetCanonicalNameWithBrackets() { + assertEquals("com.baeldung.className.RetrievingClassName[]", RetrievingClassName[].class.getCanonicalName()); + assertEquals("com.baeldung.className.RetrievingClassName[][]", RetrievingClassName[][].class.getCanonicalName()); + } + + @Test + public void givenRetrievingClassNameInnerClassArray_whenGetCanonicalName_thenRetrievingClassNameInnerClassGetCanonicalNameWithBrackets() { + assertEquals("com.baeldung.className.RetrievingClassName.InnerClass[]", RetrievingClassName.InnerClass[].class.getCanonicalName()); + assertEquals("com.baeldung.className.RetrievingClassName.InnerClass[][]", RetrievingClassName.InnerClass[][].class.getCanonicalName()); + } + +} \ No newline at end of file diff --git a/core-java/src/test/java/com/baeldung/regexp/optmization/OptimizedMatcherUnitTest.java b/core-java/src/test/java/com/baeldung/regexp/optmization/OptimizedMatcherUnitTest.java index f21a755b01..2be6b6ad4b 100644 --- a/core-java/src/test/java/com/baeldung/regexp/optmization/OptimizedMatcherUnitTest.java +++ b/core-java/src/test/java/com/baeldung/regexp/optmization/OptimizedMatcherUnitTest.java @@ -1,6 +1,5 @@ package com.baeldung.regexp.optmization; -import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -14,13 +13,15 @@ import static org.junit.Assert.assertTrue; public class OptimizedMatcherUnitTest { - private long time; - private long mstimePreCompiled; - private long mstimeNotPreCompiled; - private String action; private List items; + + private class TimeWrapper { + private long time; + private long mstimePreCompiled; + private long mstimeNotPreCompiled; + } @Before public void setup() { @@ -48,27 +49,27 @@ public class OptimizedMatcherUnitTest { @Test public void givenANotPreCompiledAndAPreCompiledPatternA_whenMatcheItems_thenPreCompiledFasterThanNotPreCompiled() { - - testPatterns("A*"); - assertTrue(mstimePreCompiled < mstimeNotPreCompiled); + TimeWrapper timeObj = new TimeWrapper(); + testPatterns("A*", timeObj); + assertTrue(timeObj.mstimePreCompiled < timeObj.mstimeNotPreCompiled); } @Test public void givenANotPreCompiledAndAPreCompiledPatternABC_whenMatcheItems_thenPreCompiledFasterThanNotPreCompiled() { - - testPatterns("A*B*C*"); - assertTrue(mstimePreCompiled < mstimeNotPreCompiled); + TimeWrapper timeObj = new TimeWrapper(); + testPatterns("A*B*C*", timeObj); + assertTrue(timeObj.mstimePreCompiled < timeObj.mstimeNotPreCompiled); } @Test public void givenANotPreCompiledAndAPreCompiledPatternECWF_whenMatcheItems_thenPreCompiledFasterThanNotPreCompiled() { - - testPatterns("E*C*W*F*"); - assertTrue(mstimePreCompiled < mstimeNotPreCompiled); + TimeWrapper timeObj = new TimeWrapper(); + testPatterns("E*C*W*F*", timeObj); + assertTrue(timeObj.mstimePreCompiled < timeObj.mstimeNotPreCompiled); } - private void testPatterns(String regex) { - time = System.nanoTime(); + private void testPatterns(String regex, TimeWrapper timeObj) { + timeObj.time = System.nanoTime(); int matched = 0; int unmatched = 0; @@ -83,10 +84,10 @@ public class OptimizedMatcherUnitTest { this.action = "uncompiled: regex=" + regex + " matched=" + matched + " unmatched=" + unmatched; - this.mstimeNotPreCompiled = (System.nanoTime() - time) / 1000000; - System.out.println(this.action + ": " + mstimeNotPreCompiled + "ms"); + timeObj.mstimeNotPreCompiled = (System.nanoTime() - timeObj.time) / 1000000; + System.out.println(this.action + ": " + timeObj.mstimeNotPreCompiled + "ms"); - time = System.nanoTime(); + timeObj.time = System.nanoTime(); Matcher matcher = Pattern.compile(regex).matcher(""); matched = 0; @@ -103,7 +104,7 @@ public class OptimizedMatcherUnitTest { this.action = "compiled: regex=" + regex + " matched=" + matched + " unmatched=" + unmatched; - this.mstimePreCompiled = (System.nanoTime() - time) / 1000000; - System.out.println(this.action + ": " + mstimePreCompiled + "ms"); + timeObj.mstimePreCompiled = (System.nanoTime() - timeObj.time) / 1000000; + System.out.println(this.action + ": " + timeObj.mstimePreCompiled + "ms"); } } diff --git a/core-java/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java b/core-java/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java new file mode 100644 index 0000000000..d952d2383b --- /dev/null +++ b/core-java/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java @@ -0,0 +1,83 @@ +package com.baeldung.string; + + +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class StringReplaceAndRemoveUnitTest { + + + @Test + public void givenTestStrings_whenReplace_thenProcessedString() { + + String master = "Hello World Baeldung!"; + String target = "Baeldung"; + String replacement = "Java"; + String processed = master.replace(target, replacement); + assertTrue(processed.contains(replacement)); + assertFalse(processed.contains(target)); + + } + + @Test + public void givenTestStrings_whenReplaceAll_thenProcessedString() { + + String master2 = "Welcome to Baeldung, Hello World Baeldung"; + String regexTarget= "(Baeldung)$"; + String replacement = "Java"; + String processed2 = master2.replaceAll(regexTarget, replacement); + assertTrue(processed2.endsWith("Java")); + + } + + @Test + public void givenTestStrings_whenStringBuilderMethods_thenProcessedString() { + + String master = "Hello World Baeldung!"; + String target = "Baeldung"; + String replacement = "Java"; + + int startIndex = master.indexOf(target); + int stopIndex = startIndex + target.length(); + + StringBuilder builder = new StringBuilder(master); + + + builder.delete(startIndex, stopIndex); + assertFalse(builder.toString().contains(target)); + + + builder.replace(startIndex, stopIndex, replacement); + assertTrue(builder.toString().contains(replacement)); + + + } + + + @Test + public void givenTestStrings_whenStringUtilsMethods_thenProcessedStrings() { + + String master = "Hello World Baeldung!"; + String target = "Baeldung"; + String replacement = "Java"; + + String processed = StringUtils.replace(master, target, replacement); + assertTrue(processed.contains(replacement)); + + String master2 = "Hello World Baeldung!"; + String target2 = "baeldung"; + String processed2 = StringUtils.replaceIgnoreCase(master2, target2, replacement); + assertFalse(processed2.contains(target)); + + } + + + + + + + +} diff --git a/core-kotlin/src/test/kotlin/com/baeldung/random/RandomStringUnitTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/random/RandomStringUnitTest.kt index 74085367e8..62e8dfe720 100644 --- a/core-kotlin/src/test/kotlin/com/baeldung/random/RandomStringUnitTest.kt +++ b/core-kotlin/src/test/kotlin/com/baeldung/random/RandomStringUnitTest.kt @@ -52,7 +52,7 @@ class RandomStringUnitTest { random.nextBytes(bytes) var randomString = (0..bytes.size - 1).map { i -> - charPool.get((bytes[i] and 0xFF.toByte() and charPool.size.toByte()).toInt()) + charPool.get((bytes[i] and 0xFF.toByte() and (charPool.size-1).toByte()).toInt()) }.joinToString("") assert(randomString.matches(Regex(ALPHANUMERIC_REGEX))) diff --git a/grpc/pom.xml b/grpc/pom.xml index 949f26d376..725bec3e70 100644 --- a/grpc/pom.xml +++ b/grpc/pom.xml @@ -71,9 +71,8 @@ - 1.5.0 - 1.5.0.Final - 0.5.0 + 1.16.1 + 1.6.1 + 0.6.1 - diff --git a/grpc/src/main/java/org/baeldung/grpc/client/GrpcClient.java b/grpc/src/main/java/org/baeldung/grpc/client/GrpcClient.java index 1a1809387f..f653e17910 100644 --- a/grpc/src/main/java/org/baeldung/grpc/client/GrpcClient.java +++ b/grpc/src/main/java/org/baeldung/grpc/client/GrpcClient.java @@ -10,7 +10,7 @@ import io.grpc.ManagedChannelBuilder; public class GrpcClient { public static void main(String[] args) throws InterruptedException { ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8080) - .usePlaintext(true) + .usePlaintext() .build(); HelloServiceGrpc.HelloServiceBlockingStub stub diff --git a/guava-collections/src/test/java/org/baeldung/guava/GuavaRangeMapUnitTest.java b/guava-collections/src/test/java/org/baeldung/guava/GuavaRangeMapUnitTest.java index 81ba72373c..c0c5efea23 100644 --- a/guava-collections/src/test/java/org/baeldung/guava/GuavaRangeMapUnitTest.java +++ b/guava-collections/src/test/java/org/baeldung/guava/GuavaRangeMapUnitTest.java @@ -2,6 +2,9 @@ package org.baeldung.guava; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; import java.util.Map; import org.junit.Test; import com.google.common.collect.ImmutableRangeMap; @@ -98,8 +101,9 @@ public class GuavaRangeMapUnitTest { final RangeMap experiencedSubRangeDesignationMap = experienceRangeDesignationMap.subRangeMap(Range.closed(4, 14)); assertNull(experiencedSubRangeDesignationMap.get(3)); - assertEquals("Executive Director", experiencedSubRangeDesignationMap.get(14)); - assertEquals("Vice President", experiencedSubRangeDesignationMap.get(7)); + assertTrue(experiencedSubRangeDesignationMap.asMapOfRanges().values() + .containsAll(Arrays.asList("Executive Director", "Vice President", "Executive Director"))); + } @Test diff --git a/java-dates/README.md b/java-dates/README.md index 66046b16a6..3f6d7998b8 100644 --- a/java-dates/README.md +++ b/java-dates/README.md @@ -24,3 +24,4 @@ - [Add Hours To a Date In Java](http://www.baeldung.com/java-add-hours-date) - [Guide to DateTimeFormatter](https://www.baeldung.com/java-datetimeformatter) - [Format ZonedDateTime to String](https://www.baeldung.com/java-format-zoned-datetime-string) +- [Convert Between java.time.Instant and java.sql.Timestamp](Convert Between java.time.Instant and java.sql.Timestamp) diff --git a/java-dates/src/test/java/com/baeldung/timestamp/StringToTimestampConverterUnitTest.java b/java-dates/src/test/java/com/baeldung/timestamp/StringToTimestampConverterUnitTest.java new file mode 100644 index 0000000000..2be646eb51 --- /dev/null +++ b/java-dates/src/test/java/com/baeldung/timestamp/StringToTimestampConverterUnitTest.java @@ -0,0 +1,22 @@ +package com.baeldung.timestamp; + +import org.junit.Assert; +import org.junit.Test; + +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class StringToTimestampConverterUnitTest { + + @Test + public void givenDatePattern_whenParsing_thenTimestampIsCorrect() { + String pattern = "MMM dd, yyyy HH:mm:ss.SSSSSSSS"; + String timestampAsString = "Nov 12, 2018 13:02:56.12345678"; + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); + LocalDateTime localDateTime = LocalDateTime.from(formatter.parse(timestampAsString)); + + Timestamp timestamp = Timestamp.valueOf(localDateTime); + Assert.assertEquals("2018-11-12 13:02:56.12345678", timestamp.toString()); + } +} \ No newline at end of file diff --git a/java-dates/src/test/java/com/baeldung/timestamp/TimestampToStringConverterTest.java b/java-dates/src/test/java/com/baeldung/timestamp/TimestampToStringConverterTest.java new file mode 100644 index 0000000000..b25ff2edb3 --- /dev/null +++ b/java-dates/src/test/java/com/baeldung/timestamp/TimestampToStringConverterTest.java @@ -0,0 +1,19 @@ +package com.baeldung.timestamp; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +import java.sql.Timestamp; +import java.time.format.DateTimeFormatter; + +public class TimestampToStringConverterTest { + + @Test + public void givenDatePattern_whenFormatting_thenResultingStringIsCorrect() { + Timestamp timestamp = Timestamp.valueOf("2018-12-12 01:02:03.123456789"); + DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; + + String timestampAsString = formatter.format(timestamp.toLocalDateTime()); + Assert.assertEquals("2018-12-12T01:02:03.123456789", timestampAsString); + } +} \ No newline at end of file diff --git a/java-strings/README.md b/java-strings/README.md index 1b24a2b821..2847a0d0a8 100644 --- a/java-strings/README.md +++ b/java-strings/README.md @@ -36,3 +36,4 @@ - [String Performance Hints](https://www.baeldung.com/java-string-performance) - [Using indexOf to Find All Occurrences of a Word in a String](https://www.baeldung.com/java-indexOf-find-string-occurrences) - [Java Base64 Encoding and Decoding](https://www.baeldung.com/java-base64-encode-and-decode) +- [Generate a Secure Random Password in Java](https://www.baeldung.com/java-generate-secure-password) diff --git a/java-strings/src/main/java/com/baeldung/string/AddingNewLineToString.java b/java-strings/src/main/java/com/baeldung/string/AddingNewLineToString.java new file mode 100644 index 0000000000..b522f7337b --- /dev/null +++ b/java-strings/src/main/java/com/baeldung/string/AddingNewLineToString.java @@ -0,0 +1,69 @@ +package com.baeldung.string; + +public class AddingNewLineToString { + + public static void main(String[] args) { + String line1 = "Humpty Dumpty sat on a wall."; + String line2 = "Humpty Dumpty had a great fall."; + String rhyme = ""; + + System.out.println("***New Line in a String in Java***"); + //1. Using "\n" + System.out.println("1. Using \\n"); + rhyme = line1 + "\n" + line2; + System.out.println(rhyme); + + //2. Using "\r\n" + System.out.println("2. Using \\r\\n"); + rhyme = line1 + "\r\n" + line2; + System.out.println(rhyme); + + //3. Using "\r" + System.out.println("3. Using \\r"); + rhyme = line1 + "\r" + line2; + System.out.println(rhyme); + + //4. Using "\n\r" Note that this is not same as "\r\n" + // Using "\n\r" is equivalent to adding two lines + System.out.println("4. Using \\n\\r"); + rhyme = line1 + "\n\r" + line2; + System.out.println(rhyme); + + //5. Using System.lineSeparator() + System.out.println("5. Using System.lineSeparator()"); + rhyme = line1 + System.lineSeparator() + line2; + System.out.println(rhyme); + + //6. Using System.getProperty("line.separator") + System.out.println("6. Using System.getProperty(\"line.separator\")"); + rhyme = line1 + System.getProperty("line.separator") + line2; + System.out.println(rhyme); + + System.out.println("***HTML to rendered in a browser***"); + //1. Line break for HTML using
+ System.out.println("1. Line break for HTML using
"); + rhyme = line1 + "
" + line2; + System.out.println(rhyme); + + //2. Line break for HTML using “ ” + System.out.println("2. Line break for HTML using "); + rhyme = line1 + " " + line2; + System.out.println(rhyme); + + //3. Line break for HTML using “ ” + System.out.println("3. Line break for HTML using "); + rhyme = line1 + " " + line2; + System.out.println(rhyme); + + //4. Line break for HTML using “ ;” + System.out.println("4. Line break for HTML using "); + rhyme = line1 + " " + line2; + System.out.println(rhyme); + + //5. Line break for HTML using \n” + System.out.println("5. Line break for HTML using \\n"); + rhyme = line1 + "\n" + line2; + System.out.println(rhyme); + } + +} \ No newline at end of file diff --git a/java-strings/src/main/java/com/baeldung/stringduplicates/RemoveDuplicateFromString.java b/java-strings/src/main/java/com/baeldung/stringduplicates/RemoveDuplicateFromString.java new file mode 100644 index 0000000000..d8fd9c4b14 --- /dev/null +++ b/java-strings/src/main/java/com/baeldung/stringduplicates/RemoveDuplicateFromString.java @@ -0,0 +1,102 @@ +package com.baeldung.stringduplicates; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; + +public class RemoveDuplicateFromString { + + + String removeDuplicatesUsingCharArray(String str) { + + char[] chars = str.toCharArray(); + StringBuilder sb = new StringBuilder(); + int repeatedCtr; + for (int i = 0; i < chars.length; i++) { + repeatedCtr = 0; + for (int j = i + 1; j < chars.length; j++) { + if (chars[i] == chars[j]) { + repeatedCtr++; + } + } + if (repeatedCtr == 0) { + sb.append(chars[i]); + } + } + return sb.toString(); + } + + String removeDuplicatesUsinglinkedHashSet(String str) { + + StringBuilder sb = new StringBuilder(); + Set linkedHashSet = new LinkedHashSet<>(); + + for (int i = 0; i < str.length(); i++) { + linkedHashSet.add(str.charAt(i)); + } + + for (Character c : linkedHashSet) { + sb.append(c); + } + + return sb.toString(); + } + + String removeDuplicatesUsingSorting(String str) { + StringBuilder sb = new StringBuilder(); + if(!str.isEmpty()) { + char[] chars = str.toCharArray(); + Arrays.sort(chars); + + sb.append(chars[0]); + for (int i = 1; i < chars.length; i++) { + if (chars[i] != chars[i - 1]) { + sb.append(chars[i]); + } + } + } + + return sb.toString(); + } + + String removeDuplicatesUsingHashSet(String str) { + + StringBuilder sb = new StringBuilder(); + Set hashSet = new HashSet<>(); + + for (int i = 0; i < str.length(); i++) { + hashSet.add(str.charAt(i)); + } + + for (Character c : hashSet) { + sb.append(c); + } + + return sb.toString(); + } + + String removeDuplicatesUsingIndexOf(String str) { + + StringBuilder sb = new StringBuilder(); + int idx; + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + idx = str.indexOf(c, i + 1); + if (idx == -1) { + sb.append(c); + } + } + return sb.toString(); + } + + + String removeDuplicatesUsingDistinct(String str) { + StringBuilder sb = new StringBuilder(); + str.chars().distinct().forEach(c -> sb.append((char) c)); + return sb.toString(); + } + +} + + diff --git a/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java b/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java new file mode 100644 index 0000000000..d952d2383b --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/string/StringReplaceAndRemoveUnitTest.java @@ -0,0 +1,83 @@ +package com.baeldung.string; + + +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class StringReplaceAndRemoveUnitTest { + + + @Test + public void givenTestStrings_whenReplace_thenProcessedString() { + + String master = "Hello World Baeldung!"; + String target = "Baeldung"; + String replacement = "Java"; + String processed = master.replace(target, replacement); + assertTrue(processed.contains(replacement)); + assertFalse(processed.contains(target)); + + } + + @Test + public void givenTestStrings_whenReplaceAll_thenProcessedString() { + + String master2 = "Welcome to Baeldung, Hello World Baeldung"; + String regexTarget= "(Baeldung)$"; + String replacement = "Java"; + String processed2 = master2.replaceAll(regexTarget, replacement); + assertTrue(processed2.endsWith("Java")); + + } + + @Test + public void givenTestStrings_whenStringBuilderMethods_thenProcessedString() { + + String master = "Hello World Baeldung!"; + String target = "Baeldung"; + String replacement = "Java"; + + int startIndex = master.indexOf(target); + int stopIndex = startIndex + target.length(); + + StringBuilder builder = new StringBuilder(master); + + + builder.delete(startIndex, stopIndex); + assertFalse(builder.toString().contains(target)); + + + builder.replace(startIndex, stopIndex, replacement); + assertTrue(builder.toString().contains(replacement)); + + + } + + + @Test + public void givenTestStrings_whenStringUtilsMethods_thenProcessedStrings() { + + String master = "Hello World Baeldung!"; + String target = "Baeldung"; + String replacement = "Java"; + + String processed = StringUtils.replace(master, target, replacement); + assertTrue(processed.contains(replacement)); + + String master2 = "Hello World Baeldung!"; + String target2 = "baeldung"; + String processed2 = StringUtils.replaceIgnoreCase(master2, target2, replacement); + assertFalse(processed2.contains(target)); + + } + + + + + + + +} diff --git a/java-strings/src/test/java/com/baeldung/stringduplicates/RemoveDuplicateFromStringUnitTest.java b/java-strings/src/test/java/com/baeldung/stringduplicates/RemoveDuplicateFromStringUnitTest.java new file mode 100644 index 0000000000..895ecc4a3b --- /dev/null +++ b/java-strings/src/test/java/com/baeldung/stringduplicates/RemoveDuplicateFromStringUnitTest.java @@ -0,0 +1,82 @@ +package com.baeldung.stringduplicates; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class RemoveDuplicateFromStringUnitTest { + + private final static String STR1 = "racecar"; + private final static String STR2 = "J2ee programming"; + private final static String STR_EMPTY = ""; + + private RemoveDuplicateFromString removeDuplicateFromString; + + @Before + public void executedBeforeEach() { + removeDuplicateFromString = new RemoveDuplicateFromString(); + } + + + @Test + public void whenUsingCharArray_DuplicatesShouldBeRemovedWithoutKeepingStringOrder() { + String str1 = removeDuplicateFromString.removeDuplicatesUsingCharArray(STR1); + String str2 = removeDuplicateFromString.removeDuplicatesUsingCharArray(STR2); + String strEmpty = removeDuplicateFromString.removeDuplicatesUsingCharArray(STR_EMPTY); + Assert.assertEquals("", strEmpty); + Assert.assertEquals("ecar", str1); + Assert.assertEquals("J2e poraming", str2); + } + + @Test + public void whenUsingLinkedHashSet_DuplicatesShouldBeRemovedAndItKeepStringOrder() { + String str1 = removeDuplicateFromString.removeDuplicatesUsinglinkedHashSet(STR1); + String str2 = removeDuplicateFromString.removeDuplicatesUsinglinkedHashSet(STR2); + + String strEmpty = removeDuplicateFromString.removeDuplicatesUsinglinkedHashSet(STR_EMPTY); + Assert.assertEquals("", strEmpty); + Assert.assertEquals("race", str1); + Assert.assertEquals("J2e progamin", str2); + } + + @Test + public void whenUsingSorting_DuplicatesShouldBeRemovedWithoutKeepingStringOrder() { + String str1 = removeDuplicateFromString.removeDuplicatesUsingSorting(STR1); + String str2 = removeDuplicateFromString.removeDuplicatesUsingSorting(STR2); + + String strEmpty = removeDuplicateFromString.removeDuplicatesUsingSorting(STR_EMPTY); + Assert.assertEquals("", strEmpty); + Assert.assertEquals("acer", str1); + Assert.assertEquals(" 2Jaegimnopr", str2); + } + + @Test + public void whenUsingHashSet_DuplicatesShouldBeRemovedWithoutKeepingStringOrder() { + String str1 = removeDuplicateFromString.removeDuplicatesUsingHashSet(STR1); + String str2 = removeDuplicateFromString.removeDuplicatesUsingHashSet(STR2); + String strEmpty = removeDuplicateFromString.removeDuplicatesUsingHashSet(STR_EMPTY); + Assert.assertEquals("", strEmpty); + Assert.assertEquals("arce", str1); + Assert.assertEquals(" pa2regiJmno", str2); + } + + @Test + public void whenUsingIndexOf_DuplicatesShouldBeRemovedWithoutKeepingStringOrder() { + String str1 = removeDuplicateFromString.removeDuplicatesUsingIndexOf(STR1); + String str2 = removeDuplicateFromString.removeDuplicatesUsingIndexOf(STR2); + String strEmpty = removeDuplicateFromString.removeDuplicatesUsingIndexOf(STR_EMPTY); + Assert.assertEquals("", strEmpty); + Assert.assertEquals("ecar", str1); + Assert.assertEquals("J2e poraming", str2); + } + + @Test + public void whenUsingJava8_DuplicatesShouldBeRemovedAndItKeepStringOrder() { + String str1 = removeDuplicateFromString.removeDuplicatesUsingDistinct(STR1); + String str2 = removeDuplicateFromString.removeDuplicatesUsingDistinct(STR2); + String strEmpty = removeDuplicateFromString.removeDuplicatesUsingDistinct(STR_EMPTY); + Assert.assertEquals("", strEmpty); + Assert.assertEquals("race", str1); + Assert.assertEquals("J2e progamin", str2); + } +} diff --git a/kotlin-libraries/pom.xml b/kotlin-libraries/pom.xml index c5b7fed951..92a643e458 100644 --- a/kotlin-libraries/pom.xml +++ b/kotlin-libraries/pom.xml @@ -87,6 +87,13 @@ h2 ${h2database.version} + + + io.arrow-kt + arrow-core + 0.7.3 + + diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEither.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEither.kt new file mode 100644 index 0000000000..75dfb9a2a4 --- /dev/null +++ b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEither.kt @@ -0,0 +1,54 @@ +package com.baeldung.kotlin.arrow + +import arrow.core.Either +import arrow.core.filterOrElse +import kotlin.math.sqrt + +class FunctionalErrorHandlingWithEither { + + sealed class ComputeProblem { + object OddNumber : ComputeProblem() + object NotANumber : ComputeProblem() + } + + fun parseInput(s : String) : Either = Either.cond(s.toIntOrNull() != null, {-> s.toInt()}, {->ComputeProblem.NotANumber} ) + + fun isEven(x : Int) : Boolean = x % 2 == 0 + + fun biggestDivisor(x: Int) : Int = biggestDivisor(x, 2) + + fun biggestDivisor(x : Int, y : Int) : Int { + if(x == y){ + return 1; + } + if(x % y == 0){ + return x / y; + } + return biggestDivisor(x, y+1) + } + + fun isSquareNumber(x : Int) : Boolean { + val sqrt: Double = sqrt(x.toDouble()) + return sqrt % 1.0 == 0.0 + } + + fun computeWithEither(input : String) : Either { + return parseInput(input) + .filterOrElse(::isEven) {->ComputeProblem.OddNumber} + .map (::biggestDivisor) + .map (::isSquareNumber) + } + + fun computeWithEitherClient(input : String) { + val computeWithEither = computeWithEither(input) + + when(computeWithEither){ + is Either.Right -> "The greatest divisor is square number: ${computeWithEither.b}" + is Either.Left -> when(computeWithEither.a){ + is ComputeProblem.NotANumber -> "Wrong input! Not a number!" + is ComputeProblem.OddNumber -> "It is an odd number!" + } + } + } + +} \ No newline at end of file diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOption.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOption.kt new file mode 100644 index 0000000000..5fddd1d88e --- /dev/null +++ b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOption.kt @@ -0,0 +1,46 @@ +package com.baeldung.kotlin.arrow + +import arrow.core.None +import arrow.core.Option +import arrow.core.Some +import kotlin.math.sqrt + +class FunctionalErrorHandlingWithOption { + + fun parseInput(s : String) : Option = Option.fromNullable(s.toIntOrNull()) + + fun isEven(x : Int) : Boolean = x % 2 == 0 + + fun biggestDivisor(x: Int) : Int = biggestDivisor(x, 2) + + fun biggestDivisor(x : Int, y : Int) : Int { + if(x == y){ + return 1; + } + if(x % y == 0){ + return x / y; + } + return biggestDivisor(x, y+1) + } + + fun isSquareNumber(x : Int) : Boolean { + val sqrt: Double = sqrt(x.toDouble()) + return sqrt % 1.0 == 0.0 + } + + fun computeWithOption(input : String) : Option { + return parseInput(input) + .filter(::isEven) + .map(::biggestDivisor) + .map(::isSquareNumber) + } + + fun computeWithOptionClient(input : String) : String{ + val computeOption = computeWithOption(input) + + return when(computeOption){ + is None -> "Not an even number!" + is Some -> "The greatest divisor is square number: ${computeOption.t}" + } + } +} \ No newline at end of file diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalDataTypes.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalDataTypes.kt new file mode 100644 index 0000000000..692425ee07 --- /dev/null +++ b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalDataTypes.kt @@ -0,0 +1,143 @@ +package com.baeldung.kotlin.arrow + +import arrow.core.* +import org.junit.Assert +import org.junit.Test + +class FunctionalDataTypes { + + @Test + fun whenIdCreated_thanValueIsPresent(){ + val id = Id("foo") + val justId = Id.just("foo"); + + Assert.assertEquals("foo", id.extract()) + Assert.assertEquals(justId, id) + } + + fun length(s : String) : Int = s.length + + fun isBigEnough(i : Int) : Boolean = i > 10 + + @Test + fun whenIdCreated_thanMapIsAssociative(){ + val foo = Id("foo") + + val map1 = foo.map(::length) + .map(::isBigEnough) + val map2 = foo.map { s -> isBigEnough(length(s)) } + + Assert.assertEquals(map1, map2) + } + + fun lengthId(s : String) : Id = Id.just(length(s)) + + fun isBigEnoughId(i : Int) : Id = Id.just(isBigEnough(i)) + + @Test + fun whenIdCreated_thanFlatMapIsAssociative(){ + val bar = Id("bar") + + val flatMap = bar.flatMap(::lengthId) + .flatMap(::isBigEnoughId) + val flatMap1 = bar.flatMap { s -> lengthId(s).flatMap(::isBigEnoughId) } + + Assert.assertEquals(flatMap, flatMap1) + } + + @Test + fun whenOptionCreated_thanValueIsPresent(){ + val factory = Option.just(42) + val constructor = Option(42) + val emptyOptional = Option.empty() + val fromNullable = Option.fromNullable(null) + + Assert.assertEquals(42, factory.getOrElse { -1 }) + Assert.assertEquals(factory, constructor) + Assert.assertEquals(emptyOptional, fromNullable) + } + + @Test + fun whenOptionCreated_thanConstructorDifferFromFactory(){ + val constructor : Option = Option(null) + val fromNullable : Option = Option.fromNullable(null) + + try{ + constructor.map { s -> s!!.length } + Assert.fail() + } catch (e : KotlinNullPointerException){ + fromNullable.map { s->s!!.length } + } + Assert.assertNotEquals(constructor, fromNullable) + } + + fun wrapper(x : Integer?) : Option = if (x == null) Option.just(-1) else Option.just(x.toInt()) + + @Test + fun whenOptionFromNullableCreated_thanItBreaksLeftIdentity(){ + val optionFromNull = Option.fromNullable(null) + + Assert.assertNotEquals(optionFromNull.flatMap(::wrapper), wrapper(null)) + } + + @Test + fun whenEitherCreated_thanOneValueIsPresent(){ + val rightOnly : Either = Either.right(42) + val leftOnly : Either = Either.left("foo") + + Assert.assertTrue(rightOnly.isRight()) + Assert.assertTrue(leftOnly.isLeft()) + Assert.assertEquals(42, rightOnly.getOrElse { -1 }) + Assert.assertEquals(-1, leftOnly.getOrElse { -1 }) + + Assert.assertEquals(0, rightOnly.map { it % 2 }.getOrElse { -1 }) + Assert.assertEquals(-1, leftOnly.map { it % 2 }.getOrElse { -1 }) + Assert.assertTrue(rightOnly.flatMap { Either.Right(it % 2) }.isRight()) + Assert.assertTrue(leftOnly.flatMap { Either.Right(it % 2) }.isLeft()) + } + + @Test + fun whenEvalNowUsed_thenMapEvaluatedLazily(){ + val now = Eval.now(1) + Assert.assertEquals(1, now.value()) + + var counter : Int = 0 + val map = now.map { x -> counter++; x+1 } + Assert.assertEquals(0, counter) + + val value = map.value() + Assert.assertEquals(2, value) + Assert.assertEquals(1, counter) + } + + @Test + fun whenEvalLaterUsed_theResultIsMemoized(){ + var counter : Int = 0 + val later = Eval.later { counter++; counter } + Assert.assertEquals(0, counter) + + val firstValue = later.value() + Assert.assertEquals(1, firstValue) + Assert.assertEquals(1, counter) + + val secondValue = later.value() + Assert.assertEquals(1, secondValue) + Assert.assertEquals(1, counter) + } + + @Test + fun whenEvalAlwaysUsed_theResultIsNotMemoized(){ + var counter : Int = 0 + val later = Eval.always { counter++; counter } + Assert.assertEquals(0, counter) + + val firstValue = later.value() + Assert.assertEquals(1, firstValue) + Assert.assertEquals(1, counter) + + val secondValue = later.value() + Assert.assertEquals(2, secondValue) + Assert.assertEquals(2, counter) + } + +} \ No newline at end of file diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEitherTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEitherTest.kt new file mode 100644 index 0000000000..47fbf825a0 --- /dev/null +++ b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEitherTest.kt @@ -0,0 +1,68 @@ +package com.baeldung.kotlin.arrow + +import arrow.core.Either +import com.baeldung.kotlin.arrow.FunctionalErrorHandlingWithEither.ComputeProblem.NotANumber +import com.baeldung.kotlin.arrow.FunctionalErrorHandlingWithEither.ComputeProblem.OddNumber +import org.junit.Assert +import org.junit.Test + +class FunctionalErrorHandlingWithEitherTest { + + val operator = FunctionalErrorHandlingWithEither() + + @Test + fun givenInvalidInput_whenComputeInvoked_NotANumberIsPresent(){ + val computeWithEither = operator.computeWithEither("bar") + + Assert.assertTrue(computeWithEither.isLeft()) + when(computeWithEither){ + is Either.Left -> when(computeWithEither.a){ + NotANumber -> "Ok." + else -> Assert.fail() + } + else -> Assert.fail() + } + } + + @Test + fun givenOddNumberInput_whenComputeInvoked_OddNumberIsPresent(){ + val computeWithEither = operator.computeWithEither("121") + + Assert.assertTrue(computeWithEither.isLeft()) + when(computeWithEither){ + is Either.Left -> when(computeWithEither.a){ + OddNumber -> "Ok." + else -> Assert.fail() + } + else -> Assert.fail() + } + } + + @Test + fun givenEvenNumberWithoutSquare_whenComputeInvoked_OddNumberIsPresent(){ + val computeWithEither = operator.computeWithEither("100") + + Assert.assertTrue(computeWithEither.isRight()) + when(computeWithEither){ + is Either.Right -> when(computeWithEither.b){ + false -> "Ok." + else -> Assert.fail() + } + else -> Assert.fail() + } + } + + @Test + fun givenEvenNumberWithSquare_whenComputeInvoked_OddNumberIsPresent(){ + val computeWithEither = operator.computeWithEither("98") + + Assert.assertTrue(computeWithEither.isRight()) + when(computeWithEither){ + is Either.Right -> when(computeWithEither.b){ + true -> "Ok." + else -> Assert.fail() + } + else -> Assert.fail() + } + } +} \ No newline at end of file diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOptionTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOptionTest.kt new file mode 100644 index 0000000000..3ca4cd033f --- /dev/null +++ b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOptionTest.kt @@ -0,0 +1,34 @@ +package com.baeldung.kotlin.arrow + +import org.junit.Assert +import org.junit.Test + +class FunctionalErrorHandlingWithOptionTest { + + val operator = FunctionalErrorHandlingWithOption() + + @Test + fun givenInvalidInput_thenErrorMessageIsPresent(){ + val useComputeOption = operator.computeWithOptionClient("foo") + Assert.assertEquals("Not an even number!", useComputeOption) + } + + @Test + fun givenOddNumberInput_thenErrorMessageIsPresent(){ + val useComputeOption = operator.computeWithOptionClient("539") + Assert.assertEquals("Not an even number!",useComputeOption) + } + + @Test + fun givenEvenNumberInputWithNonSquareNum_thenFalseMessageIsPresent(){ + val useComputeOption = operator.computeWithOptionClient("100") + Assert.assertEquals("The greatest divisor is square number: false",useComputeOption) + } + + @Test + fun givenEvenNumberInputWithSquareNum_thenTrueMessageIsPresent(){ + val useComputeOption = operator.computeWithOptionClient("242") + Assert.assertEquals("The greatest divisor is square number: true",useComputeOption) + } + +} \ No newline at end of file diff --git a/libraries/pom.xml b/libraries/pom.xml index 8ffd33272d..936e86873d 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -720,11 +720,11 @@ - + false diff --git a/logging-modules/log4j/pom.xml b/logging-modules/log4j/pom.xml index 432295fc62..1b27e03445 100644 --- a/logging-modules/log4j/pom.xml +++ b/logging-modules/log4j/pom.xml @@ -1,5 +1,6 @@ - 4.0.0 com.baeldung @@ -43,6 +44,12 @@ disruptor ${disruptor.version} + + + org.springframework.boot + spring-boot-starter-webflux + ${spring-boot.version} + @@ -50,6 +57,7 @@ 2.7 2.7 3.3.6 + 2.1.0.RELEASE \ No newline at end of file diff --git a/logging-modules/log4j/src/main/java/com/baeldung/webFluxLogging/WebFluxLoggingExample.java b/logging-modules/log4j/src/main/java/com/baeldung/webFluxLogging/WebFluxLoggingExample.java new file mode 100644 index 0000000000..f429fd57f3 --- /dev/null +++ b/logging-modules/log4j/src/main/java/com/baeldung/webFluxLogging/WebFluxLoggingExample.java @@ -0,0 +1,21 @@ +package com.baeldung.webFluxLogging; + +import reactor.core.publisher.Flux; + +public class WebFluxLoggingExample { + + public static void main(String[] args) { + Flux reactiveStream = Flux.range(1, 5).log(); + + reactiveStream.subscribe(); + + reactiveStream = Flux.range(1, 5).log().take(3); + + reactiveStream.subscribe(); + + reactiveStream = Flux.range(1, 5).take(3).log(); + + reactiveStream.subscribe(); + } + +} diff --git a/parent-boot-1/README.md b/parent-boot-1/README.md deleted file mode 100644 index ff12555376..0000000000 --- a/parent-boot-1/README.md +++ /dev/null @@ -1 +0,0 @@ -## Relevant articles: diff --git a/patterns/design-patterns/README.md b/patterns/design-patterns/README.md index 75f7cec73a..ae372bd460 100644 --- a/patterns/design-patterns/README.md +++ b/patterns/design-patterns/README.md @@ -12,3 +12,4 @@ - [The DAO Pattern in Java](http://www.baeldung.com/java-dao-pattern) - [Interpreter Design Pattern in Java](http://www.baeldung.com/java-interpreter-pattern) - [State Design Pattern in Java](https://www.baeldung.com/java-state-design-pattern) +- [The Decorator Pattern in Java](https://www.baeldung.com/java-decorator-pattern) diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/entities/DeptEmployee.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/entities/DeptEmployee.java index 27fff147b6..8b5d9c41f3 100644 --- a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/entities/DeptEmployee.java +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/entities/DeptEmployee.java @@ -10,7 +10,7 @@ public class DeptEmployee { private String employeeNumber; - private String designation; + private String title; private String name; @@ -23,11 +23,11 @@ public class DeptEmployee { this.department = department; } - public DeptEmployee(String name, String employeeNumber, String designation, Department department) { + public DeptEmployee(String name, String employeeNumber, String title, Department department) { super(); this.name = name; this.employeeNumber = employeeNumber; - this.designation = designation; + this.title = title; this.department = department; } @@ -63,11 +63,11 @@ public class DeptEmployee { this.department = department; } - public String getDesignation() { - return designation; + public String getTitle() { + return title; } - public void setDesignation(String designation) { - this.designation = designation; + public void setTitle(String title) { + this.title = title; } } diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/jpacriteriabuilder/service/EmployeeSearchService.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/jpacriteriabuilder/service/EmployeeSearchService.java index 85cdffd54d..b7d1a537f0 100644 --- a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/jpacriteriabuilder/service/EmployeeSearchService.java +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/jpacriteriabuilder/service/EmployeeSearchService.java @@ -6,9 +6,9 @@ import com.baeldung.hibernate.entities.DeptEmployee; public interface EmployeeSearchService { - List filterbyDesignationUsingCriteriaBuilder(List designaitons); + List filterbyTitleUsingCriteriaBuilder(List titles); - List filterbyDesignationUsingExpression(List aurhors); + List filterbyTitleUsingExpression(List titles); List searchByDepartmentQuery(String query); diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/jpacriteriabuilder/service/EmployeeSearchServiceImpl.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/jpacriteriabuilder/service/EmployeeSearchServiceImpl.java index a9981b8066..e79168a451 100644 --- a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/jpacriteriabuilder/service/EmployeeSearchServiceImpl.java +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/jpacriteriabuilder/service/EmployeeSearchServiceImpl.java @@ -25,12 +25,12 @@ public class EmployeeSearchServiceImpl implements EmployeeSearchService { } @Override - public List filterbyDesignationUsingCriteriaBuilder(List designations) { + public List filterbyTitleUsingCriteriaBuilder(List titles) { CriteriaQuery criteriaQuery = createCriteriaQuery(DeptEmployee.class); Root root = criteriaQuery.from(DeptEmployee.class); - In inClause = criteriaBuilder.in(root.get("designation")); - for (String designaiton : designations) { - inClause.value(designaiton); + In inClause = criteriaBuilder.in(root.get("title")); + for (String title : titles) { + inClause.value(title); } criteriaQuery.select(root) .where(inClause); @@ -39,12 +39,12 @@ public class EmployeeSearchServiceImpl implements EmployeeSearchService { } @Override - public List filterbyDesignationUsingExpression(List designations) { + public List filterbyTitleUsingExpression(List titles) { CriteriaQuery criteriaQuery = createCriteriaQuery(DeptEmployee.class); Root root = criteriaQuery.from(DeptEmployee.class); criteriaQuery.select(root) - .where(root.get("designation") - .in(designations)); + .where(root.get("title") + .in(titles)); TypedQuery query = entityManager.createQuery(criteriaQuery); return query.getResultList(); } diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/jpacriteriabuilder/EmployeeSearchServiceIntegrationTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/jpacriteriabuilder/EmployeeSearchServiceIntegrationTest.java index c7a1bc7b2a..2b12734a10 100644 --- a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/jpacriteriabuilder/EmployeeSearchServiceIntegrationTest.java +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/jpacriteriabuilder/EmployeeSearchServiceIntegrationTest.java @@ -81,42 +81,41 @@ public class EmployeeSearchServiceIntegrationTest { @Test public final void givenCriteriaQuery_whenSearchedUsingCriteriaBuilderWithListofAuthors_thenResultIsFilteredByAuthorNames() { - List designations = new ArrayList() { + List titles = new ArrayList() { { add("Manager"); add("Senior Manager"); add("Director"); } }; - List result = searchService.filterbyDesignationUsingCriteriaBuilder(designations); + List result = searchService.filterbyTitleUsingCriteriaBuilder(titles); assertEquals("Number of Employees does not match with expected.", 6, result.size()); assertThat(result.stream() - .map(DeptEmployee::getDesignation) + .map(DeptEmployee::getTitle) .distinct() - .collect(Collectors.toList()), containsInAnyOrder(designations.toArray())); + .collect(Collectors.toList()), containsInAnyOrder(titles.toArray())); } @Test public final void givenCriteriaQuery_whenSearchedUsingExpressionWithListofAuthors_thenResultIsFilteredByAuthorNames() { - List designations = new ArrayList() { + List titles = new ArrayList() { { add("Manager"); add("Senior Manager"); add("Director"); } }; - List result = searchService.filterbyDesignationUsingExpression(designations); + List result = searchService.filterbyTitleUsingExpression(titles); assertEquals("Number of Employees does not match with expected.", 6, result.size()); assertThat(result.stream() - .map(DeptEmployee::getDesignation) + .map(DeptEmployee::getTitle) .distinct() - .collect(Collectors.toList()), containsInAnyOrder(designations.toArray())); + .collect(Collectors.toList()), containsInAnyOrder(titles.toArray())); } @Test public final void givenCriteriaQuery_whenSearchedDepartmentLike_thenResultIsFilteredByDepartment() { List result = searchService.searchByDepartmentQuery("Sales"); assertEquals("Number of Employees does not match with expected.", 7, result.size()); - // assertThat(result.stream().map(DeptEmployee::getDesignation).distinct().collect(Collectors.toList()), containsInAnyOrder(designations.toArray())); } } diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/stringcast/DummyEntity.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/stringcast/Message.java similarity index 76% rename from persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/stringcast/DummyEntity.java rename to persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/stringcast/Message.java index 12b57ff112..fb521cfea6 100644 --- a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/stringcast/DummyEntity.java +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/stringcast/Message.java @@ -3,13 +3,12 @@ package com.baeldung.jpa.stringcast; import javax.persistence.*; @SqlResultSetMapping(name = "textQueryMapping", classes = { - @ConstructorResult(targetClass = DummyEntity.class, columns = { + @ConstructorResult(targetClass = Message.class, columns = { @ColumnResult(name = "text") }) }) @Entity -@Table(name = "dummy") -public class DummyEntity { +public class Message { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -17,11 +16,11 @@ public class DummyEntity { private String text; - public DummyEntity() { + public Message() { } - public DummyEntity(String text) { + public Message(String text) { this.text = text; } 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 6345e7f364..3fdc8ce27c 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 @@ -23,7 +23,7 @@ org.hibernate.jpa.HibernatePersistenceProvider - com.baeldung.jpa.stringcast.DummyEntity + com.baeldung.jpa.stringcast.Message diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/stringcast/SpringCastUnitTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/stringcast/SpringCastUnitTest.java index d9c3adef26..0a11725fc3 100644 --- a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/stringcast/SpringCastUnitTest.java +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/stringcast/SpringCastUnitTest.java @@ -3,10 +3,7 @@ package com.baeldung.jpa.stringcast; 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 javax.persistence.*; import java.util.List; import static org.junit.Assert.assertEquals; @@ -22,18 +19,18 @@ public class SpringCastUnitTest { em = emFactory.createEntityManager(); // insert an object into the db - DummyEntity dummyEntity = new DummyEntity(); - dummyEntity.setText("text"); + Message message = new Message(); + message.setText("text"); EntityTransaction tr = em.getTransaction(); tr.begin(); - em.persist(dummyEntity); + em.persist(message); tr.commit(); } @Test(expected = ClassCastException.class) public void givenExecutorNoCastCheck_whenQueryReturnsOneColumn_thenClassCastThrown() { - List results = QueryExecutor.executeNativeQueryNoCastCheck("select text from dummy", em); + List results = QueryExecutor.executeNativeQueryNoCastCheck("select text from message", em); // fails for (String[] row : results) { @@ -43,13 +40,13 @@ public class SpringCastUnitTest { @Test public void givenExecutorWithCastCheck_whenQueryReturnsOneColumn_thenNoClassCastThrown() { - List results = QueryExecutor.executeNativeQueryWithCastCheck("select text from dummy", em); + List results = QueryExecutor.executeNativeQueryWithCastCheck("select text from message", em); assertEquals("text", results.get(0)[0]); } @Test public void givenExecutorGeneric_whenQueryReturnsOneColumn_thenNoClassCastThrown() { - List results = QueryExecutor.executeNativeQueryGeneric("select text from dummy", "textQueryMapping", em); + List results = QueryExecutor.executeNativeQueryGeneric("select text from message", "textQueryMapping", em); assertEquals("text", results.get(0).getText()); } diff --git a/persistence-modules/java-jpa/src/test/resources/persistence.xml b/persistence-modules/java-jpa/src/test/resources/persistence.xml index b6cc51c3b3..c902e0a320 100644 --- a/persistence-modules/java-jpa/src/test/resources/persistence.xml +++ b/persistence-modules/java-jpa/src/test/resources/persistence.xml @@ -20,7 +20,7 @@ org.hibernate.jpa.HibernatePersistenceProvider - com.baeldung.jpa.stringcast.DummyEntity + com.baeldung.jpa.stringcast.Message diff --git a/persistence-modules/spring-boot-persistence/README.MD b/persistence-modules/spring-boot-persistence/README.MD index 6cf172426a..8988fb4ebd 100644 --- a/persistence-modules/spring-boot-persistence/README.MD +++ b/persistence-modules/spring-boot-persistence/README.MD @@ -4,3 +4,4 @@ - [Configuring Separate Spring DataSource for Tests](http://www.baeldung.com/spring-testing-separate-data-source) - [Quick Guide on data.sql and schema.sql Files in Spring Boot](http://www.baeldung.com/spring-boot-data-sql-and-schema-sql) - [Configuring a Tomcat Connection Pool in Spring Boot](https://www.baeldung.com/spring-boot-tomcat-connection-pool) +- [Hibernate Field Naming with Spring Boot](https://www.baeldung.com/hibernate-field-naming-spring-boot) diff --git a/persistence-modules/spring-data-jpa/README.md b/persistence-modules/spring-data-jpa/README.md index 44ce240da3..a65b744944 100644 --- a/persistence-modules/spring-data-jpa/README.md +++ b/persistence-modules/spring-data-jpa/README.md @@ -15,6 +15,7 @@ - [Query Entities by Dates and Times with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-query-by-date) - [DDD Aggregates and @DomainEvents](https://www.baeldung.com/spring-data-ddd) - [Spring Data – CrudRepository save() Method](https://www.baeldung.com/spring-data-crud-repository-save) +- [Limiting Query Results with JPA and Spring Data JPA](https://www.baeldung.com/jpa-limit-query-results) ### Eclipse Config After importing the project into Eclipse, you may see the following error: diff --git a/persistence-modules/spring-data-mongodb/README.md b/persistence-modules/spring-data-mongodb/README.md index c7bc7584be..c4f21dffc0 100644 --- a/persistence-modules/spring-data-mongodb/README.md +++ b/persistence-modules/spring-data-mongodb/README.md @@ -12,3 +12,4 @@ - [Spring Data MongoDB: Projections and Aggregations](http://www.baeldung.com/spring-data-mongodb-projections-aggregations) - [Spring Data Annotations](http://www.baeldung.com/spring-data-annotations) - [Spring Data MongoDB Transactions](https://www.baeldung.com/spring-data-mongodb-transactions ) +- [ZonedDateTime with Spring Data MongoDB](https://www.baeldung.com/spring-data-mongodb-zoneddatetime) diff --git a/pom.xml b/pom.xml index 109a49d985..ae5897b6f3 100644 --- a/pom.xml +++ b/pom.xml @@ -376,8 +376,6 @@ ethereum feign flips - testing-modules/gatling - geotools testing-modules/groovy-spock google-cloud google-web-toolkit @@ -740,6 +738,46 @@ helidon + + + + default-third + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + 3 + true + + **/*IntegrationTest.java + **/*IntTest.java + **/*LongRunningUnitTest.java + **/*ManualTest.java + **/*JdbcTest.java + **/*LiveTest.java + + + + + + + + + parent-boot-1 + parent-boot-2 + parent-spring-4 + parent-spring-5 + parent-java + parent-kotlin + + testing-modules/gatling + + + @@ -896,347 +934,8 @@ - - integration - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - **/*ManualTest.java - **/*LiveTest.java - - - **/*IntegrationTest.java - **/*IntTest.java - - - - - - - - - parent-boot-1 - parent-boot-2 - parent-spring-4 - parent-spring-5 - parent-java - parent-kotlin - - - - - - - - - - testing-modules/mockito - testing-modules/mockito-2 - testing-modules/mocks - mustache - mvn-wrapper - noexception - persistence-modules/orientdb - osgi - orika - patterns - pdf - protobuffer - persistence-modules/querydsl - reactor-core - persistence-modules/redis - testing-modules/rest-assured - testing-modules/rest-testing - resteasy - rxjava - rxjava-2 - spring-swagger-codegen - testing-modules/selenium-junit-testng - persistence-modules/solr - spark-java - spring-4 - spring-5 - spring-5-data-reactive - spring-5-reactive - spring-5-reactive-security - spring-5-reactive-client - spring-5-mvc - spring-5-security - spring-activiti - spring-akka - spring-amqp - spring-all - spring-amqp-simple - spring-apache-camel - spring-batch - jmh - - - - - - spring-bom - spring-boot - spring-boot-client - spring-boot-keycloak - spring-boot-bootstrap - spring-boot-admin - spring-boot-camel - spring-boot-ops - persistence-modules/spring-boot-persistence - spring-boot-security - spring-boot-mvc - spring-boot-logging-log4j2 - spring-boot-disable-console-logging - spring-cloud-data-flow - spring-cloud - spring-cloud-bus - spring-core - spring-cucumber - spring-ejb - spring-aop - persistence-modules/spring-data-cassandra - persistence-modules/spring-data-couchbase-2 - persistence-modules/spring-data-dynamodb - persistence-modules/spring-data-elasticsearch - persistence-modules/spring-data-keyvalue - persistence-modules/spring-data-mongodb - persistence-modules/spring-data-jpa - persistence-modules/spring-data-neo4j - persistence-modules/spring-data-redis - spring-data-rest - - - - - - - persistence-modules/spring-data-solr - spring-dispatcher-servlet - spring-exceptions - spring-freemarker - persistence-modules/spring-hibernate-3 - persistence-modules/spring-hibernate4 - persistence-modules/spring-hibernate-5 - persistence-modules/spring-data-eclipselink - spring-integration - spring-jenkins-pipeline - spring-jersey - spring-jms - spring-jooq - persistence-modules/spring-jpa - spring-kafka - spring-katharsis - spring-ldap - spring-mockito - spring-mvc-forms-jsp - spring-mvc-forms-thymeleaf - spring-mvc-java - spring-mvc-velocity - spring-mvc-webflow - spring-mvc-xml - spring-mvc-kotlin - spring-protobuf - spring-quartz - spring-rest-angular - spring-rest-full - spring-rest-query-language - spring-rest - spring-resttemplate - spring-rest-simple - spring-reactive-kotlin - - - - - - - - - - - - - - - - java-websocket - persistence-modules/activejdbc - animal-sniffer-mvn-plugin - apache-avro - apache-bval - apache-shiro - apache-spark - asciidoctor - checker-plugin - - - core-java-sun - custom-pmd - dagger - data-structures - dubbo - persistence-modules/flyway - - - jni - jooby - - - - ratpack - rest-with-spark-java - spring-boot-autoconfiguration - spring-boot-custom-starter - spring-boot-jasypt - spring-data-rest-querydsl - spring-groovy - spring-mobile - spring-mustache - spring-mvc-simple - spring-mybatis - spring-rest-hal-browser - spring-rest-shell - spring-rest-template - spring-roo - spring-security-stormpath - sse-jaxrs - static-analysis - stripe - - - wicket - xstream - cas/cas-secured-app - - - - - - - - - - - - - - jenkins/hello-world - - - - spring-boot-custom-starter/greeter - persistence-modules/spring-boot-h2/spring-boot-h2-database - - - - - - - - - - integration-lite-test - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - **/*ManualTest.java - **/*LiveTest.java - - - **/*IntegrationTest.java - **/*IntTest.java - - - - - - - - parent-boot-1 - parent-boot-2 - parent-spring-4 - parent-spring-5 - parent-java - parent-kotlin - - spring-4 - - - - - integration-lite + integration-lite-first @@ -1264,9 +963,9 @@ parent-spring-5 parent-java parent-kotlin + asm atomix - persistence-modules/apache-cayenne aws aws-lambda akka-streams @@ -1286,25 +985,30 @@ autovalue axon azure + apache-velocity + apache-solrj + apache-meecrowave + antlr + bootique + cdi - java-strings - core-java-collections - java-collections-conversions - java-collections-maps core-java-io core-java-8 - java-streams core-groovy - couchbase - persistence-modules/deltaspike + dozer + disruptor + drools + deeplearning4j + ethereum + feign flips - testing-modules/groovy-spock + google-cloud gson guava @@ -1313,17 +1017,20 @@ guava-modules/guava-19 guava-modules/guava-21 guice - disruptor - spring-static-resources + hazelcast - persistence-modules/hbase - hystrix + httpclient + image-processing immutables - persistence-modules/influxdb + jackson - vavr + java-strings + + java-collections-conversions + java-collections-maps + java-streams java-lite java-numbers java-rmi @@ -1341,47 +1048,108 @@ json jsoup jta - testing-modules/junit-5 - testing-modules/junit5-migration jws + jersey + java-spi + java-ee-8-security-api + libraries-data linkrest logging-modules/log-mdc logging-modules/log4j - logging-modules/logback lombok + lucene + mapstruct - maven mesos-marathon msf4j - testing-modules/mockito - testing-modules/mockito-2 - testing-modules/mocks mustache mvn-wrapper + mybatis + metrics + maven-archetype + noexception - persistence-modules/orientdb + osgi orika + patterns pdf protobuffer - persistence-modules/querydsl - reactor-core + performance-tests + + persistence-modules/java-jdbi persistence-modules/redis - testing-modules/rest-assured - testing-modules/rest-testing + persistence-modules/orientdb + persistence-modules/querydsl + persistence-modules/apache-cayenne + persistence-modules/solr + persistence-modules/spring-data-dynamodb + persistence-modules/spring-data-keyvalue + persistence-modules/spring-data-neo4j + persistence-modules/spring-data-solr + persistence-modules/spring-hibernate-5 + persistence-modules/spring-data-eclipselink + persistence-modules/spring-jpa + persistence-modules/spring-hibernate-3 + persistence-modules/spring-data-gemfire + persistence-modules/spring-boot-persistence + persistence-modules/liquibase + persistence-modules/java-cockroachdb + persistence-modules/deltaspike + persistence-modules/hbase + persistence-modules/influxdb + persistence-modules/spring-hibernate4 + + reactor-core resteasy rxjava rxjava-2 - spring-swagger-codegen - testing-modules/selenium-junit-testng - persistence-modules/solr - spark-java + rabbitmq + + + + + + + + + + integration-lite-second + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*ManualTest.java + **/*LiveTest.java + + + **/*IntegrationTest.java + **/*IntTest.java + + + + + + + + parent-boot-1 + parent-boot-2 + parent-spring-4 + parent-spring-5 + parent-java + parent-kotlin + spring-4 - spring-5-data-reactive spring-5-reactive spring-5-reactive-security spring-5-reactive-client @@ -1391,19 +1159,19 @@ spring-akka spring-amqp spring-all - spring-amqp-simple spring-apache-camel spring-batch spring-bom + spring-boot-keycloak spring-boot-bootstrap spring-boot-admin spring-boot-camel - persistence-modules/spring-boot-persistence spring-boot-security spring-boot-mvc spring-boot-logging-log4j2 spring-boot-disable-console-logging + spring-cloud-data-flow spring-cloud spring-cloud-bus @@ -1411,28 +1179,18 @@ spring-cucumber spring-ejb spring-aop - - persistence-modules/spring-data-dynamodb - persistence-modules/spring-data-keyvalue - persistence-modules/spring-data-mongodb - persistence-modules/spring-data-neo4j - + spring-data-rest - persistence-modules/spring-data-solr spring-dispatcher-servlet spring-exceptions spring-freemarker - persistence-modules/spring-hibernate-3 - persistence-modules/spring-hibernate-5 - persistence-modules/spring-data-eclipselink spring-integration spring-jenkins-pipeline spring-jersey spring-jms spring-jooq - persistence-modules/spring-jpa spring-kafka spring-katharsis spring-ldap @@ -1490,54 +1248,88 @@ spring-vault spring-jinq spring-rest-embedded-tomcat + + spring-static-resources + spring-swagger-codegen + spring-drools + spring-boot-property-exp + spring-security-thymeleaf + spring-boot-ctx-fluent + spring-webflux-amqp + + + + + + + + + + integration-lite-third + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*ManualTest.java + **/*LiveTest.java + + + **/*IntegrationTest.java + **/*IntTest.java + + + + + + + + parent-boot-1 + parent-boot-2 + parent-spring-4 + parent-spring-5 + parent-java + parent-kotlin + + spark-java + saas + struts-2 + + testing-modules/selenium-junit-testng + testing-modules/groovy-spock + testing-modules/mockito + testing-modules/mockito-2 + testing-modules/mocks + testing-modules/rest-assured + testing-modules/rest-testing + testing-modules/junit-5 + testing-modules/junit5-migration testing-modules/testing testing-modules/testng - video-tutorials - - xmlunit-2 - struts-2 - apache-velocity - apache-solrj - rabbitmq - - persistence-modules/spring-data-gemfire - mybatis - spring-drools - drools - persistence-modules/liquibase - spring-boot-property-exp testing-modules/mockserver testing-modules/test-containers + twilio + undertow + + video-tutorials vaadin vertx-and-rxjava - saas - deeplearning4j - lucene vraptor - persistence-modules/java-cockroachdb - spring-security-thymeleaf - persistence-modules/java-jdbi - jersey - java-spi - performance-tests - twilio - spring-boot-ctx-fluent - java-ee-8-security-api - spring-webflux-amqp - antlr - maven-archetype - apache-meecrowave - - persistence-modules/spring-hibernate4 - xml vertx - metrics - httpclient - + vavr + + xmlunit-2 + xml + + + + + + + + + + testing-modules/mockito + testing-modules/mockito-2 + testing-modules/mocks + mustache + mvn-wrapper + noexception + persistence-modules/orientdb + osgi + orika + patterns + pdf + protobuffer + persistence-modules/querydsl + reactor-core + persistence-modules/redis + testing-modules/rest-assured + testing-modules/rest-testing + resteasy + rxjava + rxjava-2 + spring-swagger-codegen + testing-modules/selenium-junit-testng + persistence-modules/solr + spark-java + spring-4 + spring-5 + spring-5-data-reactive + spring-5-reactive + spring-5-reactive-security + spring-5-reactive-client + spring-5-mvc + spring-5-security + spring-activiti + spring-akka + spring-amqp + spring-all + spring-amqp-simple + spring-apache-camel + spring-batch + jmh + + + + + + spring-bom + spring-boot + spring-boot-client + spring-boot-keycloak + spring-boot-bootstrap + spring-boot-admin + spring-boot-camel + spring-boot-ops + persistence-modules/spring-boot-persistence + spring-boot-security + spring-boot-mvc + spring-boot-logging-log4j2 + spring-boot-disable-console-logging + spring-cloud-data-flow + spring-cloud + spring-cloud-bus + spring-core + spring-cucumber + spring-ejb + spring-aop + persistence-modules/spring-data-cassandra + persistence-modules/spring-data-couchbase-2 + persistence-modules/spring-data-dynamodb + persistence-modules/spring-data-elasticsearch + persistence-modules/spring-data-keyvalue + persistence-modules/spring-data-mongodb + persistence-modules/spring-data-jpa + persistence-modules/spring-data-neo4j + persistence-modules/spring-data-redis + spring-data-rest + + + + + + + persistence-modules/spring-data-solr + spring-dispatcher-servlet + spring-exceptions + spring-freemarker + persistence-modules/spring-hibernate-3 + persistence-modules/spring-hibernate4 + persistence-modules/spring-hibernate-5 + persistence-modules/spring-data-eclipselink + spring-integration + spring-jenkins-pipeline + spring-jersey + spring-jms + spring-jooq + persistence-modules/spring-jpa + spring-kafka + spring-katharsis + spring-ldap + spring-mockito + spring-mvc-forms-jsp + spring-mvc-forms-thymeleaf + spring-mvc-java + spring-mvc-velocity + spring-mvc-webflow + spring-mvc-xml + spring-mvc-kotlin + spring-protobuf + spring-quartz + spring-rest-angular + spring-rest-full + spring-rest-query-language + spring-rest + spring-resttemplate + spring-rest-simple + spring-reactive-kotlin + + + + + + + + + + + + + + + + java-websocket + persistence-modules/activejdbc + animal-sniffer-mvn-plugin + apache-avro + apache-bval + apache-shiro + apache-spark + asciidoctor + checker-plugin + + + core-java-sun + custom-pmd + dagger + data-structures + dubbo + persistence-modules/flyway + + + jni + jooby + + + + ratpack + rest-with-spark-java + spring-boot-autoconfiguration + spring-boot-custom-starter + spring-boot-jasypt + spring-data-rest-querydsl + spring-groovy + spring-mobile + spring-mustache + spring-mvc-simple + spring-mybatis + spring-rest-hal-browser + spring-rest-shell + spring-rest-template + spring-roo + spring-security-stormpath + sse-jaxrs + static-analysis + stripe + + + wicket + xstream + cas/cas-secured-app + + + + + + + + + + + + + + jenkins/hello-world + + + + spring-boot-custom-starter/greeter + persistence-modules/spring-boot-h2/spring-boot-h2-database + + + + + + + + integration-heavy @@ -1637,7 +1733,7 @@ true false false - + false 4.12 1.3 diff --git a/spring-5-reactive-oauth/README.md b/spring-5-reactive-oauth/README.md new file mode 100644 index 0000000000..0f27cf5d20 --- /dev/null +++ b/spring-5-reactive-oauth/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Spring Security OAuth Login with WebFlux](https://www.baeldung.com/spring-oauth-login-webflux) diff --git a/spring-all/README.md b/spring-all/README.md index 34e5c3435e..0d78efdcf2 100644 --- a/spring-all/README.md +++ b/spring-all/README.md @@ -33,3 +33,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring Cache – Creating a Custom KeyGenerator](http://www.baeldung.com/spring-cache-custom-keygenerator) - [Spring @Primary Annotation](http://www.baeldung.com/spring-primary) - [Spring Events](https://www.baeldung.com/spring-events) +- [Spring Null-Safety Annotations](https://www.baeldung.com/spring-null-safety-annotations) diff --git a/spring-amqp-simple/pom.xml b/spring-amqp-simple/pom.xml index 3d9ea55cfa..ea9c227d8c 100644 --- a/spring-amqp-simple/pom.xml +++ b/spring-amqp-simple/pom.xml @@ -5,7 +5,6 @@ com.baeldung spring-amqp-simple 1.0.0-SNAPSHOT - Spring AMQP Simple App parent-boot-1 diff --git a/spring-boot-mvc/README.md b/spring-boot-mvc/README.md index e7b42f8f50..bf32e4fc7c 100644 --- a/spring-boot-mvc/README.md +++ b/spring-boot-mvc/README.md @@ -9,3 +9,4 @@ - [Display RSS Feed with Spring MVC](http://www.baeldung.com/spring-mvc-rss-feed) - [A Controller, Service and DAO Example with Spring Boot and JSF](https://www.baeldung.com/jsf-spring-boot-controller-service-dao) - [Cache Eviction in Spring Boot](https://www.baeldung.com/spring-boot-evict-cache) +- [Setting Up Swagger 2 with a Spring REST API](http://www.baeldung.com/swagger-2-documentation-for-spring-rest-api) \ No newline at end of file diff --git a/spring-boot-mvc/pom.xml b/spring-boot-mvc/pom.xml index 5f6cdff85b..b219e53431 100644 --- a/spring-boot-mvc/pom.xml +++ b/spring-boot-mvc/pom.xml @@ -15,6 +15,7 @@ + org.springframework.boot spring-boot-starter-web @@ -23,6 +24,7 @@ org.apache.tomcat.embed tomcat-embed-jasper + org.glassfish @@ -30,17 +32,13 @@ 2.3.7 + org.springframework.boot spring-boot-starter-test test - - org.springframework.boot - spring-boot-starter-validation - - com.rometools @@ -48,6 +46,7 @@ ${rome.version} + org.hibernate.validator hibernate-validator @@ -56,6 +55,23 @@ javax.validation validation-api + + org.springframework.boot + spring-boot-starter-validation + + + + + io.springfox + springfox-swagger2 + ${spring.fox.version} + + + io.springfox + springfox-swagger-ui + ${spring.fox.version} + + @@ -72,6 +88,7 @@ + 2.9.2 1.10.0 com.baeldung.springbootmvc.SpringBootMvcApplication diff --git a/spring-boot-mvc/src/main/java/com/baeldung/swaggerboot/Application.java b/spring-boot-mvc/src/main/java/com/baeldung/swaggerboot/Application.java new file mode 100644 index 0000000000..14e46b2306 --- /dev/null +++ b/spring-boot-mvc/src/main/java/com/baeldung/swaggerboot/Application.java @@ -0,0 +1,13 @@ +package com.baeldung.swaggerboot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} \ No newline at end of file diff --git a/spring-boot-mvc/src/main/java/com/baeldung/swaggerboot/configuration/SpringFoxConfig.java b/spring-boot-mvc/src/main/java/com/baeldung/swaggerboot/configuration/SpringFoxConfig.java new file mode 100644 index 0000000000..3041dfdcc8 --- /dev/null +++ b/spring-boot-mvc/src/main/java/com/baeldung/swaggerboot/configuration/SpringFoxConfig.java @@ -0,0 +1,68 @@ +package com.baeldung.swaggerboot.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger.web.*; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import java.util.Collections; + +@Configuration +@EnableSwagger2 +@ComponentScan("com.baeldung.swaggerboot.controller") +public class SpringFoxConfig { + + private ApiInfo apiInfo() { + return new ApiInfo( + "My REST API", + "Some custom description of API.", + "API TOS", + "Terms of service", + new Contact("John Doe", "www.example.com", "myeaddress@company.com"), + "License of API", + "API license URL", + Collections.emptyList()); + } + + @Bean + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo()) + .select() + .apis(RequestHandlerSelectors.any()) + .paths(PathSelectors.any()) + .build(); + } + + /** + * SwaggerUI information + */ + + @Bean + UiConfiguration uiConfig() { + return UiConfigurationBuilder.builder() + .deepLinking(true) + .displayOperationId(false) + .defaultModelsExpandDepth(1) + .defaultModelExpandDepth(1) + .defaultModelRendering(ModelRendering.EXAMPLE) + .displayRequestDuration(false) + .docExpansion(DocExpansion.NONE) + .filter(false) + .maxDisplayedTags(null) + .operationsSorter(OperationsSorter.ALPHA) + .showExtensions(false) + .tagsSorter(TagsSorter.ALPHA) + .supportedSubmitMethods(UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS) + .validatorUrl(null) + .build(); + } + +} diff --git a/spring-boot-mvc/src/main/java/com/baeldung/swaggerboot/controller/RegularRestController.java b/spring-boot-mvc/src/main/java/com/baeldung/swaggerboot/controller/RegularRestController.java new file mode 100644 index 0000000000..676937f7d7 --- /dev/null +++ b/spring-boot-mvc/src/main/java/com/baeldung/swaggerboot/controller/RegularRestController.java @@ -0,0 +1,14 @@ +package com.baeldung.swaggerboot.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class RegularRestController { + + @GetMapping("home") + public String getSession() { + return "Hello"; + } + +} \ No newline at end of file diff --git a/spring-boot-mvc/src/main/resources/application.properties b/spring-boot-mvc/src/main/resources/application.properties index e69de29bb2..709574239b 100644 --- a/spring-boot-mvc/src/main/resources/application.properties +++ b/spring-boot-mvc/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.main.allow-bean-definition-overriding=true \ No newline at end of file diff --git a/spring-boot/.attach_pid12812 b/spring-boot/.attach_pid12812 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-boot/README.MD b/spring-boot/README.MD index f09ab27fb5..016d2841d7 100644 --- a/spring-boot/README.MD +++ b/spring-boot/README.MD @@ -34,4 +34,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Introduction to Chaos Monkey](https://www.baeldung.com/spring-boot-chaos-monkey) - [Spring Component Scanning](https://www.baeldung.com/spring-component-scanning) - [Load Spring Boot Properties From a JSON File](https://www.baeldung.com/spring-boot-json-properties) -- [Display Auto-Configuration Report in Spring Boot](https://www.baeldung.com/spring-boot-auto-configuration-report) \ No newline at end of file +- [Display Auto-Configuration Report in Spring Boot](https://www.baeldung.com/spring-boot-auto-configuration-report) +- [Injecting Git Information Into Spring](https://www.baeldung.com/spring-git-information) diff --git a/spring-boot/pom.xml b/spring-boot/pom.xml index f16460b7c3..87c782b044 100644 --- a/spring-boot/pom.xml +++ b/spring-boot/pom.xml @@ -1,4 +1,5 @@ - 4.0.0 spring-boot @@ -55,6 +56,14 @@ org.springframework.boot spring-boot-starter-data-jpa + + org.ehcache + ehcache + + + org.hibernate + hibernate-ehcache + org.springframework.boot spring-boot-starter-actuator @@ -70,6 +79,11 @@ graphql-java-tools ${graphql-java-tools.version} + + com.graphql-java + graphiql-spring-boot-starter + ${graphiql-spring-boot-starter.version} + org.springframework.boot @@ -143,10 +157,10 @@ chaos-monkey-spring-boot ${chaos.monkey.version} - + - javax.validation - validation-api + javax.validation + validation-api @@ -170,6 +184,26 @@ pl.project13.maven git-commit-id-plugin ${git-commit-id-plugin.version} + + + get-the-git-infos + + revision + + initialize + + + validate-the-git-infos + + validateRevision + + package + + + + true + ${project.build.outputDirectory}/git.properties + @@ -220,10 +254,11 @@ 2.4.1.Final 1.9.0 2.0.0 - 3.6.0 - 3.2.0 + 5.0.2 + 5.0.2 + 5.2.4 18.0 - 2.2.4 + 2.2.4 diff --git a/spring-boot/src/main/java/com/baeldung/dynamicvalidation/ContactInfoValidator.java b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/ContactInfoValidator.java index e079b9a665..cc05fd4fbd 100644 --- a/spring-boot/src/main/java/com/baeldung/dynamicvalidation/ContactInfoValidator.java +++ b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/ContactInfoValidator.java @@ -30,7 +30,7 @@ public class ContactInfoValidator implements ConstraintValidator { - Optional findOne(String id); + Optional findById(String id); } diff --git a/spring-boot/src/main/java/com/baeldung/failureanalyzer/FailureAnalyzerApplication.java b/spring-boot/src/main/java/com/baeldung/failureanalyzer/FailureAnalyzerApplication.java index 3489732b6f..7bd5c36786 100644 --- a/spring-boot/src/main/java/com/baeldung/failureanalyzer/FailureAnalyzerApplication.java +++ b/spring-boot/src/main/java/com/baeldung/failureanalyzer/FailureAnalyzerApplication.java @@ -9,7 +9,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; public class FailureAnalyzerApplication { @RolesAllowed("*") public static void main(String[] args) { - System.setProperty("security.basic.enabled", "false"); SpringApplication.run(FailureAnalyzerApplication.class, args); } } diff --git a/spring-boot/src/main/java/com/baeldung/internationalization/InternationalizationApp.java b/spring-boot/src/main/java/com/baeldung/internationalization/InternationalizationApp.java index c92d1c32e6..c3af611f3b 100644 --- a/spring-boot/src/main/java/com/baeldung/internationalization/InternationalizationApp.java +++ b/spring-boot/src/main/java/com/baeldung/internationalization/InternationalizationApp.java @@ -9,7 +9,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; public class InternationalizationApp { @RolesAllowed("*") public static void main(String[] args) { - System.setProperty("security.basic.enabled", "false"); SpringApplication.run(InternationalizationApp.class, args); } } diff --git a/spring-boot/src/main/java/com/baeldung/rss/RssApp.java b/spring-boot/src/main/java/com/baeldung/rss/RssApp.java index d3d3d0241f..e067d3cfd1 100644 --- a/spring-boot/src/main/java/com/baeldung/rss/RssApp.java +++ b/spring-boot/src/main/java/com/baeldung/rss/RssApp.java @@ -1,18 +1,17 @@ package com.baeldung.rss; +import javax.annotation.security.RolesAllowed; + import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; -import javax.annotation.security.RolesAllowed; - @SpringBootApplication @ComponentScan(basePackages = "com.baeldung.rss") public class RssApp { @RolesAllowed("*") public static void main(String[] args) { - System.setProperty("security.basic.enabled", "false"); SpringApplication.run(RssApp.class, args); } diff --git a/spring-boot/src/main/java/com/baeldung/toggle/ToggleApplication.java b/spring-boot/src/main/java/com/baeldung/toggle/ToggleApplication.java index 27be6b7cca..fa84cf0d9b 100644 --- a/spring-boot/src/main/java/com/baeldung/toggle/ToggleApplication.java +++ b/spring-boot/src/main/java/com/baeldung/toggle/ToggleApplication.java @@ -9,7 +9,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; public class ToggleApplication { @RolesAllowed("*") public static void main(String[] args) { - System.setProperty("security.basic.enabled", "false"); SpringApplication.run(ToggleApplication.class, args); } } diff --git a/spring-boot/src/main/java/org/baeldung/session/exception/Application.java b/spring-boot/src/main/java/org/baeldung/session/exception/Application.java index 9132e710d1..354c64c258 100644 --- a/spring-boot/src/main/java/org/baeldung/session/exception/Application.java +++ b/spring-boot/src/main/java/org/baeldung/session/exception/Application.java @@ -4,8 +4,6 @@ import org.baeldung.demo.model.Foo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.context.annotation.Bean; -import org.springframework.orm.jpa.vendor.HibernateJpaSessionFactoryBean; @EntityScan(basePackageClasses = Foo.class) @SpringBootApplication @@ -15,9 +13,4 @@ public class Application { System.setProperty("spring.profiles.active", "exception"); SpringApplication.run(Application.class, args); } - - @Bean - public HibernateJpaSessionFactoryBean sessionFactory() { - return new HibernateJpaSessionFactoryBean(); - } } diff --git a/spring-boot/src/main/java/org/baeldung/session/exception/repository/FooRepositoryImpl.java b/spring-boot/src/main/java/org/baeldung/session/exception/repository/FooRepositoryImpl.java index 52407a2117..607bae83ba 100644 --- a/spring-boot/src/main/java/org/baeldung/session/exception/repository/FooRepositoryImpl.java +++ b/spring-boot/src/main/java/org/baeldung/session/exception/repository/FooRepositoryImpl.java @@ -1,5 +1,7 @@ package org.baeldung.session.exception.repository; +import javax.persistence.EntityManagerFactory; + import org.baeldung.demo.model.Foo; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -10,16 +12,15 @@ import org.springframework.stereotype.Repository; @Repository public class FooRepositoryImpl implements FooRepository { @Autowired - private SessionFactory sessionFactory; + private EntityManagerFactory emf; @Override public void save(Foo foo) { - sessionFactory.getCurrentSession().saveOrUpdate(foo); + emf.unwrap(SessionFactory.class).getCurrentSession().saveOrUpdate(foo); } @Override public Foo get(Integer id) { - return sessionFactory.getCurrentSession().get(Foo.class, id); + return emf.unwrap(SessionFactory.class).getCurrentSession().get(Foo.class, id); } - } \ No newline at end of file diff --git a/spring-boot/src/main/resources/META-INF/spring.factories b/spring-boot/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000000..e3d3aa4c8e --- /dev/null +++ b/spring-boot/src/main/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.boot.diagnostics.FailureAnalyzer=com.baeldung.failureanalyzer.MyBeanNotOfRequiredTypeFailureAnalyzer \ No newline at end of file diff --git a/spring-boot/src/main/resources/application.properties b/spring-boot/src/main/resources/application.properties index 629e880940..6a52dd1f70 100644 --- a/spring-boot/src/main/resources/application.properties +++ b/spring-boot/src/main/resources/application.properties @@ -7,7 +7,7 @@ spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto = update management.endpoints.jmx.domain=Spring Sample Application -management.endpoints.jmx.uniqueNames=true +spring.jmx.unique-names=true management.endpoints.web.exposure.include=* management.endpoint.shutdown.enabled=true @@ -17,7 +17,6 @@ management.endpoint.shutdown.enabled=true ##endpoints.jolokia.path=jolokia spring.jmx.enabled=true -management.endpoints.jmx.enabled=true ## for pretty printing of json when endpoints accessed over HTTP http.mappers.jsonPrettyPrint=true diff --git a/spring-boot/src/main/resources/demo.properties b/spring-boot/src/main/resources/demo.properties index 649b64f59b..6b4cbeb7a0 100644 --- a/spring-boot/src/main/resources/demo.properties +++ b/spring-boot/src/main/resources/demo.properties @@ -1,6 +1,2 @@ spring.output.ansi.enabled=never server.port=7070 - -# Security -security.user.name=admin -security.user.password=password \ No newline at end of file diff --git a/spring-boot/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithServletComponentIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithServletComponentIntegrationTest.java index 2c3ac2e159..8c85934fac 100644 --- a/spring-boot/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithServletComponentIntegrationTest.java +++ b/spring-boot/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithServletComponentIntegrationTest.java @@ -20,7 +20,6 @@ import static org.junit.Assert.assertTrue; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringBootAnnotatedApp.class) -@TestPropertySource(properties = { "security.basic.enabled=false" }) public class SpringBootWithServletComponentIntegrationTest { @Autowired diff --git a/spring-boot/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithoutServletComponentIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithoutServletComponentIntegrationTest.java index a30d3ed3f2..c29cd75e9d 100644 --- a/spring-boot/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithoutServletComponentIntegrationTest.java +++ b/spring-boot/src/test/java/com/baeldung/annotation/servletcomponentscan/SpringBootWithoutServletComponentIntegrationTest.java @@ -19,7 +19,6 @@ import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringBootPlainApp.class) -@TestPropertySource(properties = { "security.basic.enabled=false" }) public class SpringBootWithoutServletComponentIntegrationTest { @Autowired diff --git a/spring-boot/src/test/java/com/baeldung/displayallbeans/DisplayBeanIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/displayallbeans/DisplayBeanIntegrationTest.java index aab4836b6f..e933920a96 100644 --- a/spring-boot/src/test/java/com/baeldung/displayallbeans/DisplayBeanIntegrationTest.java +++ b/spring-boot/src/test/java/com/baeldung/displayallbeans/DisplayBeanIntegrationTest.java @@ -1,31 +1,34 @@ package com.baeldung.displayallbeans; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.BDDAssertions.then; + +import java.net.URI; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; + import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.actuate.beans.BeansEndpoint.ContextBeans; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.web.context.WebApplicationContext; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import static org.assertj.core.api.BDDAssertions.then; -import static org.hamcrest.CoreMatchers.hasItem; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; - @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@TestPropertySource(properties = { "management.port=0", "endpoints.beans.id=springbeans", "endpoints.beans.sensitive=false" }) +@TestPropertySource(properties = { "management.port=0", "management.endpoints.web.exposure.include=*" }) public class DisplayBeanIntegrationTest { @LocalServerPort @@ -40,6 +43,8 @@ public class DisplayBeanIntegrationTest { @Autowired private WebApplicationContext context; + private static final String ACTUATOR_PATH = "/actuator"; + @Test public void givenRestTemplate_whenAccessServerUrl_thenHttpStatusOK() throws Exception { ResponseEntity entity = this.testRestTemplate.getForEntity("http://localhost:" + this.port + "/displayallbeans", String.class); @@ -49,22 +54,27 @@ public class DisplayBeanIntegrationTest { @Test public void givenRestTemplate_whenAccessEndpointUrl_thenHttpStatusOK() throws Exception { - @SuppressWarnings("rawtypes") - ResponseEntity entity = this.testRestTemplate.getForEntity("http://localhost:" + this.mgt + "/springbeans", List.class); + ParameterizedTypeReference> responseType = new ParameterizedTypeReference>() { + }; + RequestEntity requestEntity = RequestEntity.get(new URI("http://localhost:" + this.mgt + ACTUATOR_PATH + "/beans")) + .accept(MediaType.APPLICATION_JSON) + .build(); + ResponseEntity> entity = this.testRestTemplate.exchange(requestEntity, responseType); then(entity.getStatusCode()).isEqualTo(HttpStatus.OK); } @Test public void givenRestTemplate_whenAccessEndpointUrl_thenReturnsBeanNames() throws Exception { - @SuppressWarnings("rawtypes") - ResponseEntity entity = this.testRestTemplate.getForEntity("http://localhost:" + this.mgt + "/springbeans", List.class); + RequestEntity requestEntity = RequestEntity.get(new URI("http://localhost:" + this.mgt + ACTUATOR_PATH + "/beans")) + .accept(MediaType.APPLICATION_JSON) + .build(); + ResponseEntity entity = this.testRestTemplate.exchange(requestEntity, BeanActuatorResponse.class); - List> allBeans = (List) ((Map) entity.getBody().get(0)).get("beans"); - List beanNamesList = allBeans.stream().map(x -> (String) x.get("bean")).collect(Collectors.toList()); + Collection beanNamesList = entity.getBody() + .getBeans(); - assertThat(beanNamesList, hasItem("fooController")); - assertThat(beanNamesList, hasItem("fooService")); + assertThat(beanNamesList).contains("fooController", "fooService"); } @Test @@ -72,7 +82,20 @@ public class DisplayBeanIntegrationTest { String[] beanNames = context.getBeanDefinitionNames(); List beanNamesList = Arrays.asList(beanNames); - assertTrue(beanNamesList.contains("fooController")); - assertTrue(beanNamesList.contains("fooService")); + assertThat(beanNamesList).contains("fooController", "fooService"); + } + + private static class BeanActuatorResponse { + private Map>>> contexts; + + public Collection getBeans() { + return this.contexts.get("application") + .get("beans") + .keySet(); + } + + public Map>>> getContexts() { + return contexts; + } } } diff --git a/spring-boot/src/test/java/com/baeldung/failureanalyzer/FailureAnalyzerAppIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/failureanalyzer/FailureAnalyzerAppIntegrationTest.java new file mode 100644 index 0000000000..b3555f55da --- /dev/null +++ b/spring-boot/src/test/java/com/baeldung/failureanalyzer/FailureAnalyzerAppIntegrationTest.java @@ -0,0 +1,47 @@ +package com.baeldung.failureanalyzer; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Collection; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.boot.SpringApplication; + +import com.baeldung.failureanalyzer.utils.ListAppender; + +import ch.qos.logback.classic.spi.ILoggingEvent; + +public class FailureAnalyzerAppIntegrationTest { + + private static final String EXPECTED_ANALYSIS_DESCRIPTION_TITLE = "Description:"; + private static final String EXPECTED_ANALYSIS_DESCRIPTION_CONTENT = "The bean myDAO could not be injected as com.baeldung.failureanalyzer.MyDAO because it is of type com.baeldung.failureanalyzer.MySecondDAO"; + private static final String EXPECTED_ANALYSIS_ACTION_TITLE = "Action:"; + private static final String EXPECTED_ANALYSIS_ACTION_CONTENT = "Consider creating a bean with name myDAO of type com.baeldung.failureanalyzer.MyDAO"; + + @BeforeEach + public void clearLogList() { + ListAppender.clearEventList(); + } + + @Test + public void givenBeanCreationErrorInContext_whenContextLoaded_thenFailureAnalyzerLogsReport() { + try { + SpringApplication.run(FailureAnalyzerApplication.class); + } catch (BeanCreationException e) { + Collection allLoggedEntries = ListAppender.getEvents() + .stream() + .map(ILoggingEvent::getFormattedMessage) + .collect(Collectors.toList()); + assertThat(allLoggedEntries).anyMatch(entry -> entry.contains(EXPECTED_ANALYSIS_DESCRIPTION_TITLE)) + .anyMatch(entry -> entry.contains(EXPECTED_ANALYSIS_DESCRIPTION_CONTENT)) + .anyMatch(entry -> entry.contains(EXPECTED_ANALYSIS_ACTION_TITLE)) + .anyMatch(entry -> entry.contains(EXPECTED_ANALYSIS_ACTION_CONTENT)); + return; + } + throw new IllegalStateException("Context load should be failing due to a BeanCreationException!"); + } + +} diff --git a/spring-boot/src/test/java/com/baeldung/failureanalyzer/utils/ListAppender.java b/spring-boot/src/test/java/com/baeldung/failureanalyzer/utils/ListAppender.java new file mode 100644 index 0000000000..a298f49ff5 --- /dev/null +++ b/spring-boot/src/test/java/com/baeldung/failureanalyzer/utils/ListAppender.java @@ -0,0 +1,25 @@ +package com.baeldung.failureanalyzer.utils; + +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.AppenderBase; + +public class ListAppender extends AppenderBase { + + static private List events = new ArrayList<>(); + + @Override + protected void append(ILoggingEvent eventObject) { + events.add(eventObject); + } + + public static List getEvents() { + return events; + } + + public static void clearEventList() { + events.clear(); + } +} \ No newline at end of file diff --git a/spring-boot/src/test/java/com/baeldung/git/CommitIdIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/git/CommitIdIntegrationTest.java index 348d594c05..d7399a4ff5 100644 --- a/spring-boot/src/test/java/com/baeldung/git/CommitIdIntegrationTest.java +++ b/spring-boot/src/test/java/com/baeldung/git/CommitIdIntegrationTest.java @@ -1,17 +1,19 @@ package com.baeldung.git; +import static org.assertj.core.api.Assertions.assertThat; + import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; -import static org.assertj.core.api.Assertions.assertThat; - @RunWith(SpringRunner.class) @ContextConfiguration(classes = CommitIdApplication.class) +@TestPropertySource(properties = { "spring.jmx.default-domain=test" }) public class CommitIdIntegrationTest { private static final Logger LOG = LoggerFactory.getLogger(CommitIdIntegrationTest.class); diff --git a/spring-boot/src/test/java/com/baeldung/intro/AppLiveTest.java b/spring-boot/src/test/java/com/baeldung/intro/AppLiveTest.java index 83b893ae5c..44461c0cf6 100644 --- a/spring-boot/src/test/java/com/baeldung/intro/AppLiveTest.java +++ b/spring-boot/src/test/java/com/baeldung/intro/AppLiveTest.java @@ -18,7 +18,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK) @AutoConfigureMockMvc -@TestPropertySource(properties = { "security.basic.enabled=false" }) public class AppLiveTest { @Autowired diff --git a/spring-boot/src/test/java/com/baeldung/kong/KongAdminAPILiveTest.java b/spring-boot/src/test/java/com/baeldung/kong/KongAdminAPILiveTest.java index 5cf19dd1db..92d2286518 100644 --- a/spring-boot/src/test/java/com/baeldung/kong/KongAdminAPILiveTest.java +++ b/spring-boot/src/test/java/com/baeldung/kong/KongAdminAPILiveTest.java @@ -55,7 +55,7 @@ public class KongAdminAPILiveTest { public void givenKongAdminAPI_whenAddAPI_thenAPIAccessibleViaKong() throws Exception { restTemplate.delete("http://localhost:8001/apis/stock-api"); - APIObject stockAPI = new APIObject("stock-api", "stock.api", "http://localhost:8080", "/"); + APIObject stockAPI = new APIObject("stock-api", "stock.api", "http://localhost:9090", "/"); HttpEntity apiEntity = new HttpEntity<>(stockAPI); ResponseEntity addAPIResp = restTemplate.postForEntity("http://localhost:8001/apis", apiEntity, String.class); @@ -69,7 +69,7 @@ public class KongAdminAPILiveTest { HttpHeaders headers = new HttpHeaders(); headers.set("Host", "stock.api"); - RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, new URI("http://localhost:8000/stock/btc")); + RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, new URI("http://localhost:8000/springbootapp/stock/btc")); ResponseEntity stockPriceResp = restTemplate.exchange(requestEntity, String.class); assertEquals("10000", stockPriceResp.getBody()); @@ -126,22 +126,26 @@ public class KongAdminAPILiveTest { givenKongAdminAPI_whenAddAPIConsumer_thenAdded(); } + PluginObject authPlugin = new PluginObject("key-auth"); + ResponseEntity enableAuthResp = restTemplate.postForEntity("http://localhost:8001/apis/stock-api/plugins", new HttpEntity<>(authPlugin), String.class); + assertTrue(HttpStatus.CREATED == enableAuthResp.getStatusCode() || HttpStatus.CONFLICT == enableAuthResp.getStatusCode()); + final String consumerKey = "eugenp.pass"; KeyAuthObject keyAuth = new KeyAuthObject(consumerKey); ResponseEntity keyAuthResp = restTemplate.postForEntity("http://localhost:8001/consumers/eugenp/key-auth", new HttpEntity<>(keyAuth), String.class); - + assertTrue(HttpStatus.CREATED == keyAuthResp.getStatusCode() || HttpStatus.CONFLICT == keyAuthResp.getStatusCode()); HttpHeaders headers = new HttpHeaders(); headers.set("Host", "stock.api"); headers.set("apikey", consumerKey); - RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, new URI("http://localhost:8000/stock/btc")); + RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, new URI("http://localhost:8000/springbootapp/stock/btc")); ResponseEntity stockPriceResp = restTemplate.exchange(requestEntity, String.class); assertEquals("10000", stockPriceResp.getBody()); headers.set("apikey", "wrongpass"); - requestEntity = new RequestEntity<>(headers, HttpMethod.GET, new URI("http://localhost:8000/stock/btc")); + requestEntity = new RequestEntity<>(headers, HttpMethod.GET, new URI("http://localhost:8000/springbootapp/stock/btc")); stockPriceResp = restTemplate.exchange(requestEntity, String.class); assertEquals(HttpStatus.FORBIDDEN, stockPriceResp.getStatusCode()); } diff --git a/spring-boot/src/test/java/com/baeldung/kong/KongLoadBalanceLiveTest.java b/spring-boot/src/test/java/com/baeldung/kong/KongLoadBalanceLiveTest.java index abc7151720..7cf67453a6 100644 --- a/spring-boot/src/test/java/com/baeldung/kong/KongLoadBalanceLiveTest.java +++ b/spring-boot/src/test/java/com/baeldung/kong/KongLoadBalanceLiveTest.java @@ -1,28 +1,34 @@ package com.baeldung.kong; -import com.baeldung.kong.domain.APIObject; -import com.baeldung.kong.domain.TargetObject; -import com.baeldung.kong.domain.UpstreamObject; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT; + +import java.net.URI; + 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.boot.test.web.client.TestRestTemplate; -import org.springframework.http.*; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit4.SpringRunner; -import java.net.URI; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT; +import com.baeldung.kong.domain.APIObject; +import com.baeldung.kong.domain.TargetObject; +import com.baeldung.kong.domain.UpstreamObject; /** * @author aiet */ @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = DEFINED_PORT, classes = StockApp.class) +@SpringBootTest(webEnvironment = DEFINED_PORT, classes = StockApp.class, properties = "server.servlet.contextPath=/springbootapp") public class KongLoadBalanceLiveTest { @Before @@ -55,13 +61,13 @@ public class KongLoadBalanceLiveTest { HttpHeaders headers = new HttpHeaders(); headers.set("Host", "balanced.stock.api"); for (int i = 0; i < 1000; i++) { - RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, new URI("http://localhost:8000/stock/btc")); + RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, new URI("http://localhost:8000/springbootapp/stock/btc")); ResponseEntity stockPriceResp = restTemplate.exchange(requestEntity, String.class); assertEquals("10000", stockPriceResp.getBody()); } - int releaseCount = restTemplate.getForObject("http://localhost:9090/stock/reqcount", Integer.class); - int testCount = restTemplate.getForObject("http://localhost:8080/stock/reqcount", Integer.class); + int releaseCount = restTemplate.getForObject("http://localhost:9090/springbootapp/stock/reqcount", Integer.class); + int testCount = restTemplate.getForObject("http://localhost:8080/springbootapp/stock/reqcount", Integer.class); assertTrue(Math.round(releaseCount * 1.0 / testCount) == 4); } diff --git a/spring-boot/src/test/java/com/baeldung/mongodb/ManualEmbeddedMongoDbIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/mongodb/ManualEmbeddedMongoDbIntegrationTest.java index 30a4d61fbd..c49b99ed99 100644 --- a/spring-boot/src/test/java/com/baeldung/mongodb/ManualEmbeddedMongoDbIntegrationTest.java +++ b/spring-boot/src/test/java/com/baeldung/mongodb/ManualEmbeddedMongoDbIntegrationTest.java @@ -7,6 +7,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.util.SocketUtils; import com.mongodb.BasicDBObjectBuilder; import com.mongodb.DBObject; @@ -32,16 +33,16 @@ class ManualEmbeddedMongoDbIntegrationTest { @BeforeEach void setup() throws Exception { String ip = "localhost"; - int port = 27017; + int randomPort = SocketUtils.findAvailableTcpPort(); IMongodConfig mongodConfig = new MongodConfigBuilder().version(Version.Main.PRODUCTION) - .net(new Net(ip, port, Network.localhostIsIPv6())) + .net(new Net(ip, randomPort, Network.localhostIsIPv6())) .build(); MongodStarter starter = MongodStarter.getDefaultInstance(); mongodExecutable = starter.prepare(mongodConfig); mongodExecutable.start(); - mongoTemplate = new MongoTemplate(new MongoClient(ip, port), "test"); + mongoTemplate = new MongoTemplate(new MongoClient(ip, randomPort), "test"); } @DisplayName("Given object When save object using MongoDB template Then object can be found") diff --git a/spring-boot/src/test/resources/application.properties b/spring-boot/src/test/resources/application.properties index 85e4e6e66f..9ad65e1815 100644 --- a/spring-boot/src/test/resources/application.properties +++ b/spring-boot/src/test/resources/application.properties @@ -2,7 +2,6 @@ spring.mail.host=localhost spring.mail.port=8025 spring.mail.properties.mail.smtp.auth=false -security.basic.enabled=false # spring.datasource.x spring.datasource.driver-class-name=org.h2.Driver @@ -11,9 +10,10 @@ spring.datasource.username=sa spring.datasource.password=sa # 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 +spring.jpa.hibernate.dialect=org.hibernate.dialect.H2Dialect +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.hibernate.show_sql=true +spring.jpa.hibernate.hbm2ddl.auto=create-drop +spring.jpa.hibernate.cache.use_second_level_cache=true +spring.jpa.hibernate.cache.use_query_cache=true +spring.jpa.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory diff --git a/spring-boot/src/test/resources/exception.properties b/spring-boot/src/test/resources/exception.properties index c55e415a3a..2d17b64a25 100644 --- a/spring-boot/src/test/resources/exception.properties +++ b/spring-boot/src/test/resources/exception.properties @@ -1,6 +1,2 @@ -# Security -security.user.name=admin -security.user.password=password - spring.dao.exceptiontranslation.enabled=false -spring.profiles.active=exception \ No newline at end of file +spring.profiles.active=exception diff --git a/spring-boot/src/test/resources/logback-test.xml b/spring-boot/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..9e0f4e221f --- /dev/null +++ b/spring-boot/src/test/resources/logback-test.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-cloud/README.md b/spring-cloud/README.md index 16bc2d110a..dc43bd1a66 100644 --- a/spring-cloud/README.md +++ b/spring-cloud/README.md @@ -30,3 +30,4 @@ - [Introduction to Netflix Archaius with Spring Cloud](https://www.baeldung.com/netflix-archaius-spring-cloud-integration) - [An Intro to Spring Cloud Vault](https://www.baeldung.com/spring-cloud-vault) - [Netflix Archaius with Various Database Configurations](https://www.baeldung.com/netflix-archaius-database-configurations) +- [Rate Limiting in Spring Cloud Netflix Zuul](https://www.baeldung.com/spring-cloud-zuul-rate-limit) diff --git a/spring-data-rest/README.md b/spring-data-rest/README.md index 09f8391406..db94a86a6f 100644 --- a/spring-data-rest/README.md +++ b/spring-data-rest/README.md @@ -20,3 +20,4 @@ To view the running application, visit [http://localhost:8080](http://localhost: - [List of In-Memory Databases](http://www.baeldung.com/java-in-memory-databases) - [Projections and Excerpts in Spring Data REST](http://www.baeldung.com/spring-data-rest-projections-excerpts) - [Spring Data REST Events with @RepositoryEventHandler](http://www.baeldung.com/spring-data-rest-events) +- [Customizing HTTP Endpoints in Spring Data REST](https://www.baeldung.com/spring-data-rest-customize-http-endpoints) diff --git a/spring-integration/src/main/java/com/baeldung/subflows/discardflow/FilterExample.java b/spring-integration/src/main/java/com/baeldung/subflows/discardflow/FilterExample.java new file mode 100644 index 0000000000..f0e12f9333 --- /dev/null +++ b/spring-integration/src/main/java/com/baeldung/subflows/discardflow/FilterExample.java @@ -0,0 +1,57 @@ +package com.baeldung.subflows.discardflow; + +import java.util.Collection; +import org.springframework.context.annotation.Bean; +import org.springframework.integration.annotation.Gateway; +import org.springframework.integration.annotation.IntegrationComponentScan; +import org.springframework.integration.annotation.MessagingGateway; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.integration.config.EnableIntegration; +import org.springframework.integration.dsl.IntegrationFlow; + +@EnableIntegration +@IntegrationComponentScan +public class FilterExample { + @MessagingGateway + public interface NumbersClassifier { + @Gateway(requestChannel = "classify.input") + void classify(Collection numbers); + } + + @Bean + QueueChannel multipleofThreeChannel() { + return new QueueChannel(); + } + + @Bean + QueueChannel remainderIsOneChannel() { + return new QueueChannel(); + } + + @Bean + QueueChannel remainderIsTwoChannel() { + return new QueueChannel(); + } + boolean isMultipleOfThree(Integer number) { + return number % 3 == 0; + } + + boolean isRemainderOne(Integer number) { + return number % 3 == 1; + } + + boolean isRemainderTwo(Integer number) { + return number % 3 == 2; + } + @Bean + public IntegrationFlow classify() { + return flow -> flow.split() + . filter(this::isMultipleOfThree, notMultiple -> notMultiple + .discardFlow(oneflow -> oneflow + . filter(this::isRemainderOne, + twoflow -> twoflow .discardChannel("remainderIsTwoChannel")) + .channel("remainderIsOneChannel"))) + .channel("multipleofThreeChannel"); + } + +} \ No newline at end of file diff --git a/spring-integration/src/main/java/com/baeldung/subflows/publishsubscribechannel/PublishSubscibeChannelExample.java b/spring-integration/src/main/java/com/baeldung/subflows/publishsubscribechannel/PublishSubscibeChannelExample.java index e26f938632..a1a448fc03 100644 --- a/spring-integration/src/main/java/com/baeldung/subflows/publishsubscribechannel/PublishSubscibeChannelExample.java +++ b/spring-integration/src/main/java/com/baeldung/subflows/publishsubscribechannel/PublishSubscibeChannelExample.java @@ -1,15 +1,13 @@ package com.baeldung.subflows.publishsubscribechannel; -import java.util.Arrays; import java.util.Collection; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.integration.annotation.Gateway; import org.springframework.integration.annotation.IntegrationComponentScan; import org.springframework.integration.annotation.MessagingGateway; -import org.springframework.integration.channel.DirectChannel; + +import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.config.EnableIntegration; import org.springframework.integration.dsl.IntegrationFlow; @@ -18,46 +16,45 @@ import org.springframework.integration.dsl.IntegrationFlow; public class PublishSubscibeChannelExample { @MessagingGateway public interface NumbersClassifier { - @Gateway(requestChannel = "flow.input") - void flow(Collection numbers); + @Gateway(requestChannel = "classify.input") + void classify(Collection numbers); } @Bean - DirectChannel multipleof3Channel() { - return new DirectChannel(); + QueueChannel multipleofThreeChannel() { + return new QueueChannel(); } @Bean - DirectChannel remainderIs1Channel() { - return new DirectChannel(); + QueueChannel remainderIsOneChannel() { + return new QueueChannel(); } @Bean - DirectChannel remainderIs2Channel() { - return new DirectChannel(); + QueueChannel remainderIsTwoChannel() { + return new QueueChannel(); + } + boolean isMultipleOfThree(Integer number) { + return number % 3 == 0; } + boolean isRemainderOne(Integer number) { + return number % 3 == 1; + } + + boolean isRemainderTwo(Integer number) { + return number % 3 == 2; + } @Bean - public IntegrationFlow flow() { + public IntegrationFlow classify() { return flow -> flow.split() - .publishSubscribeChannel(s -> s.subscribe(f -> f. filter(p -> p % 3 == 0) - .channel("multipleof3Channel")) - .subscribe(f -> f. filter(p -> p % 3 == 1) - .channel("remainderIs1Channel")) - .subscribe(f -> f. filter(p -> p % 3 == 2) - .channel("remainderIs2Channel"))); + .publishSubscribeChannel(subscription -> subscription.subscribe(subflow -> subflow. filter(this::isMultipleOfThree) + .channel("multipleofThreeChannel")) + .subscribe(subflow -> subflow. filter(this::isRemainderOne) + .channel("remainderIsOneChannel")) + .subscribe(subflow -> subflow. filter(this::isRemainderTwo) + .channel("remainderIsTwoChannel"))); } + - public static void main(String[] args) { - final ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(PublishSubscibeChannelExample.class); - DirectChannel multipleof3Channel = ctx.getBean("multipleof3Channel", DirectChannel.class); - multipleof3Channel.subscribe(x -> System.out.println("multipleof3Channel: " + x)); - DirectChannel remainderIs1Channel = ctx.getBean("remainderIs1Channel", DirectChannel.class); - remainderIs1Channel.subscribe(x -> System.out.println("remainderIs1Channel: " + x)); - DirectChannel remainderIs2Channel = ctx.getBean("remainderIs2Channel", DirectChannel.class); - remainderIs2Channel.subscribe(x -> System.out.println("remainderIs2Channel: " + x)); - ctx.getBean(NumbersClassifier.class) - .flow(Arrays.asList(1, 2, 3, 4, 5, 6)); - ctx.close(); - } } diff --git a/spring-integration/src/main/java/com/baeldung/subflows/routeToRecipients/RouteToRecipientsExample.java b/spring-integration/src/main/java/com/baeldung/subflows/routeToRecipients/RouteToRecipientsExample.java index 04fdb87dfa..e0b4841736 100644 --- a/spring-integration/src/main/java/com/baeldung/subflows/routeToRecipients/RouteToRecipientsExample.java +++ b/spring-integration/src/main/java/com/baeldung/subflows/routeToRecipients/RouteToRecipientsExample.java @@ -1,15 +1,12 @@ -package com.baeldung.subflows.routeToRecipients; +package com.baeldung.subflows.routetorecipients; -import java.util.Arrays; import java.util.Collection; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.integration.annotation.Gateway; import org.springframework.integration.annotation.IntegrationComponentScan; import org.springframework.integration.annotation.MessagingGateway; -import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.config.EnableIntegration; import org.springframework.integration.dsl.IntegrationFlow; @@ -18,44 +15,46 @@ import org.springframework.integration.dsl.IntegrationFlow; public class RouteToRecipientsExample { @MessagingGateway public interface NumbersClassifier { - @Gateway(requestChannel = "flow.input") - void flow(Collection numbers); + @Gateway(requestChannel = "classify.input") + void classify(Collection numbers); } @Bean - DirectChannel multipleof3Channel() { - return new DirectChannel(); + QueueChannel multipleofThreeChannel() { + return new QueueChannel(); } @Bean - DirectChannel remainderIs1Channel() { - return new DirectChannel(); + QueueChannel remainderIsOneChannel() { + return new QueueChannel(); } @Bean - DirectChannel remainderIs2Channel() { - return new DirectChannel(); + QueueChannel remainderIsTwoChannel() { + return new QueueChannel(); + } + boolean isMultipleOfThree(Integer number) { + return number % 3 == 0; + } + + boolean isRemainderOne(Integer number) { + return number % 3 == 1; + } + + boolean isRemainderTwo(Integer number) { + return number % 3 == 2; } @Bean - public IntegrationFlow flow() { + public IntegrationFlow classify() { return flow -> flow.split() - .routeToRecipients(r -> r. recipient("multipleof3Channel", p -> p % 3 == 0)// filter - . recipient("remainderIs1Channel", p -> p % 3 == 1) - .recipientFlow(sf -> sf. filter(p -> p % 3 == 2) - .channel("remainderIs2Channel"))); + .routeToRecipients(route -> route + .recipientFlow(subflow -> subflow + . filter(this::isMultipleOfThree) + .channel("multipleofThreeChannel")) + . recipient("remainderIsOneChannel",this::isRemainderOne) + . recipient("remainderIsTwoChannel",this::isRemainderTwo)); } + - public static void main(String[] args) { - final ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(RouteToRecipientsExample.class); - DirectChannel multipleof3Channel = ctx.getBean("multipleof3Channel", DirectChannel.class); - multipleof3Channel.subscribe(x -> System.out.println("multipleof3Channel: " + x)); - DirectChannel remainderIs1Channel = ctx.getBean("remainderIs1Channel", DirectChannel.class); - remainderIs1Channel.subscribe(x -> System.out.println("remainderIs1Channel: " + x)); - DirectChannel remainderIs2Channel = ctx.getBean("remainderIs2Channel", DirectChannel.class); - remainderIs2Channel.subscribe(x -> System.out.println("remainderIs2Channel: " + x)); - ctx.getBean(NumbersClassifier.class) - .flow(Arrays.asList(1, 2, 3, 4, 5, 6)); - ctx.close(); - } } \ No newline at end of file diff --git a/spring-integration/src/main/java/com/baeldung/subflows/separateflows/SeparateFlowsExample.java b/spring-integration/src/main/java/com/baeldung/subflows/separateflows/SeparateFlowsExample.java index 8ed46ead87..457b8045c5 100644 --- a/spring-integration/src/main/java/com/baeldung/subflows/separateflows/SeparateFlowsExample.java +++ b/spring-integration/src/main/java/com/baeldung/subflows/separateflows/SeparateFlowsExample.java @@ -1,15 +1,13 @@ package com.baeldung.subflows.separateflows; -import java.util.Arrays; import java.util.Collection; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.integration.annotation.Gateway; import org.springframework.integration.annotation.IntegrationComponentScan; import org.springframework.integration.annotation.MessagingGateway; -import org.springframework.integration.channel.DirectChannel; + +import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.config.EnableIntegration; import org.springframework.integration.dsl.IntegrationFlow; @@ -18,66 +16,62 @@ import org.springframework.integration.dsl.IntegrationFlow; public class SeparateFlowsExample { @MessagingGateway public interface NumbersClassifier { - @Gateway(requestChannel = "multipleof3Flow.input") - void multipleof3(Collection is); + @Gateway(requestChannel = "multipleOfThreeFlow.input") + void multipleofThree(Collection numbers); - @Gateway(requestChannel = "remainderIs1Flow.input") - void remainderIs1(Collection is); + @Gateway(requestChannel = "remainderIsOneFlow.input") + void remainderIsOne(Collection numbers); - @Gateway(requestChannel = "remainderIs2Flow.input") - void remainderIs2(Collection numbers); + @Gateway(requestChannel = "remainderIsTwoFlow.input") + void remainderIsTwo(Collection numbers); + } + + @Bean + QueueChannel multipleOfThreeChannel() { + return new QueueChannel(); + } + + @Bean + QueueChannel remainderIsOneChannel() { + return new QueueChannel(); + } + + @Bean + QueueChannel remainderIsTwoChannel() { + return new QueueChannel(); + } + + boolean isMultipleOfThree(Integer number) { + return number % 3 == 0; + } + + boolean isRemainderOne(Integer number) { + return number % 3 == 1; + } + + boolean isRemainderTwo(Integer number) { + return number % 3 == 2; } @Bean - DirectChannel multipleof3Channel() { - return new DirectChannel(); + public IntegrationFlow multipleOfThreeFlow() { + return flow -> flow.split() + . filter(this::isMultipleOfThree) + .channel("multipleOfThreeChannel"); } @Bean - DirectChannel remainderIs1Channel() { - return new DirectChannel(); + public IntegrationFlow remainderIsOneFlow() { + return flow -> flow.split() + . filter(this::isRemainderOne) + .channel("remainderIsOneChannel"); } @Bean - DirectChannel remainderIs2Channel() { - return new DirectChannel(); + public IntegrationFlow remainderIsTwoFlow() { + return flow -> flow.split() + . filter(this::isRemainderTwo) + .channel("remainderIsTwoChannel"); } - @Bean - public IntegrationFlow multipleof3Flow() { - return f -> f.split() - . filter(p -> p % 3 == 0) - .channel("multipleof3Channel"); - } - - @Bean - public IntegrationFlow remainderIs1Flow() { - return f -> f.split() - . filter(p -> p % 3 == 1) - .channel("remainderIs1Channel"); - } - - @Bean - public IntegrationFlow remainderIs2Flow() { - return f -> f.split() - . filter(p -> p % 3 == 2) - .channel("remainderIs2Channel"); - } - - public static void main(String[] args) { - final ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(SeparateFlowsExample.class); - DirectChannel multipleof3Channel = ctx.getBean("multipleof3Channel", DirectChannel.class); - multipleof3Channel.subscribe(x -> System.out.println("multipleof3Channel: " + x)); - DirectChannel remainderIs1Channel = ctx.getBean("remainderIs1Channel", DirectChannel.class); - remainderIs1Channel.subscribe(x -> System.out.println("remainderIs1Channel: " + x)); - DirectChannel remainderIs2Channel = ctx.getBean("remainderIs2Channel", DirectChannel.class); - remainderIs2Channel.subscribe(x -> System.out.println("remainderIs2Channel: " + x)); - ctx.getBean(NumbersClassifier.class) - .multipleof3(Arrays.asList(1, 2, 3, 4, 5, 6)); - ctx.getBean(NumbersClassifier.class) - .remainderIs1(Arrays.asList(1, 2, 3, 4, 5, 6)); - ctx.getBean(NumbersClassifier.class) - .remainderIs2(Arrays.asList(1, 2, 3, 4, 5, 6)); - ctx.close(); - } } \ No newline at end of file diff --git a/spring-integration/src/main/java/com/baeldung/subflows/subflowchannel/FilterExample.java b/spring-integration/src/main/java/com/baeldung/subflows/subflowchannel/FilterExample.java deleted file mode 100644 index 6db3741523..0000000000 --- a/spring-integration/src/main/java/com/baeldung/subflows/subflowchannel/FilterExample.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.baeldung.subflows.subflowchannel; - -import java.util.Arrays; -import java.util.Collection; - -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.integration.annotation.Gateway; -import org.springframework.integration.annotation.IntegrationComponentScan; -import org.springframework.integration.annotation.MessagingGateway; -import org.springframework.integration.channel.DirectChannel; -import org.springframework.integration.config.EnableIntegration; -import org.springframework.integration.dsl.IntegrationFlow; - -@EnableIntegration -@IntegrationComponentScan -public class FilterExample { - @MessagingGateway - public interface NumbersClassifier { - @Gateway(requestChannel = "flow.input") - void flow(Collection numbers); - } - - @Bean - DirectChannel multipleof3Channel() { - return new DirectChannel(); - } - - @Bean - DirectChannel remainderIs1Channel() { - return new DirectChannel(); - } - - @Bean - DirectChannel remainderIs2Channel() { - return new DirectChannel(); - } - - @Bean - public IntegrationFlow flow() { - return flow -> flow.split() - . filter(x -> x % 3 == 0, sf -> sf.discardFlow(subf -> subf. filter(x -> x % 3 == 1, ssf -> ssf.discardChannel("remainderIs2Channel")) - .channel("remainderIs1Channel"))) - .channel("multipleof3Channel"); - } - - public static void main(String[] args) { - final ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(FilterExample.class); - DirectChannel multipleof3Channel = ctx.getBean("multipleof3Channel", DirectChannel.class); - multipleof3Channel.subscribe(x -> System.out.println("multipleof3Channel: " + x)); - DirectChannel remainderIs1Channel = ctx.getBean("remainderIs1Channel", DirectChannel.class); - remainderIs1Channel.subscribe(x -> System.out.println("remainderIs1Channel: " + x)); - DirectChannel remainderIs2Channel = ctx.getBean("remainderIs2Channel", DirectChannel.class); - remainderIs2Channel.subscribe(x -> System.out.println("remainderIs2Channel: " + x)); - ctx.getBean(NumbersClassifier.class) - .flow(Arrays.asList(1, 2, 3, 4, 5, 6)); - ctx.close(); - } -} \ No newline at end of file diff --git a/spring-integration/src/main/java/com/baeldung/subflows/subflowmapping/RouterExample.java b/spring-integration/src/main/java/com/baeldung/subflows/subflowmapping/RouterExample.java index de1f11cf70..c0e902e739 100644 --- a/spring-integration/src/main/java/com/baeldung/subflows/subflowmapping/RouterExample.java +++ b/spring-integration/src/main/java/com/baeldung/subflows/subflowmapping/RouterExample.java @@ -1,15 +1,11 @@ package com.baeldung.subflows.subflowmapping; -import java.util.Arrays; import java.util.Collection; - -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.integration.annotation.Gateway; import org.springframework.integration.annotation.IntegrationComponentScan; import org.springframework.integration.annotation.MessagingGateway; -import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.config.EnableIntegration; import org.springframework.integration.dsl.IntegrationFlow; @@ -18,44 +14,49 @@ import org.springframework.integration.dsl.IntegrationFlow; public class RouterExample { @MessagingGateway public interface NumbersClassifier { - @Gateway(requestChannel = "flow.input") - void flow(Collection numbers); + @Gateway(requestChannel = "classify.input") + void classify(Collection numbers); } @Bean - DirectChannel multipleof3Channel() { - return new DirectChannel(); + QueueChannel multipleofThreeChannel() { + return new QueueChannel(); } @Bean - DirectChannel remainderIs1Channel() { - return new DirectChannel(); + QueueChannel remainderIsOneChannel() { + return new QueueChannel(); } @Bean - DirectChannel remainderIs2Channel() { - return new DirectChannel(); + QueueChannel remainderIsTwoChannel() { + return new QueueChannel(); + } + + boolean isMultipleOfThree(Integer number) { + return number % 3 == 0; + } + + boolean isRemainderOne(Integer number) { + return number % 3 == 1; + } + + boolean isRemainderTwo(Integer number) { + return number % 3 == 2; } @Bean - public IntegrationFlow flow() { - return f -> f.split() - . route(p -> p % 3, m -> m.channelMapping(0, "multipleof3Channel") - .subFlowMapping(1, sf -> sf.channel("remainderIs1Channel")) - .subFlowMapping(2, sf -> sf. handle((p, h) -> p))) - .channel("remainderIs2Channel"); + public IntegrationFlow classify() { + return flow -> flow.split() + . route(number -> number % 3, + mapping -> mapping + .channelMapping(0, "multipleofThreeChannel") + .subFlowMapping(1, subflow -> subflow.channel("remainderIsOneChannel")) + .subFlowMapping(2, subflow -> subflow + . handle((payload, headers) -> { + // do extra work on the payload + return payload; + }))).channel("remainderIsTwoChannel"); } - public static void main(String[] args) { - final ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(RouterExample.class); - DirectChannel multipleof3Channel = ctx.getBean("multipleof3Channel", DirectChannel.class); - multipleof3Channel.subscribe(x -> System.out.println("multipleof3Channel: " + x)); - DirectChannel remainderIs1Channel = ctx.getBean("remainderIs1Channel", DirectChannel.class); - remainderIs1Channel.subscribe(x -> System.out.println("remainderIs1Channel: " + x)); - DirectChannel remainderIs2Channel = ctx.getBean("remainderIs2Channel", DirectChannel.class); - remainderIs2Channel.subscribe(x -> System.out.println("remainderIs2Channel: " + x)); - ctx.getBean(NumbersClassifier.class) - .flow(Arrays.asList(1, 2, 3, 4, 5, 6)); - ctx.close(); - } } \ No newline at end of file diff --git a/spring-integration/src/test/java/com/baeldung/subflows/discardflow/FilterUnitTest.java b/spring-integration/src/test/java/com/baeldung/subflows/discardflow/FilterUnitTest.java new file mode 100644 index 0000000000..3b3106212b --- /dev/null +++ b/spring-integration/src/test/java/com/baeldung/subflows/discardflow/FilterUnitTest.java @@ -0,0 +1,62 @@ +package com.baeldung.subflows.discardflow; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.messaging.Message; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.baeldung.subflows.discardflow.FilterExample.NumbersClassifier; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { FilterExample.class }) +public class FilterUnitTest { + @Autowired + private QueueChannel multipleofThreeChannel; + + @Autowired + private QueueChannel remainderIsOneChannel; + + @Autowired + private QueueChannel remainderIsTwoChannel; + + @Autowired + private NumbersClassifier numbersClassifier; + + @Test + public void whenSendMessagesToFlow_thenNumbersAreClassified() { + + numbersClassifier.classify(Arrays.asList(1, 2, 3, 4, 5, 6)); + + Message outMessage = multipleofThreeChannel.receive(0); + + assertEquals(outMessage.getPayload(), 3); + + outMessage = multipleofThreeChannel.receive(0); + + assertEquals(outMessage.getPayload(), 6); + + outMessage = remainderIsOneChannel.receive(0); + + assertEquals(outMessage.getPayload(), 1); + outMessage = remainderIsOneChannel.receive(0); + + assertEquals(outMessage.getPayload(), 4); + + outMessage = remainderIsTwoChannel.receive(0); + + assertEquals(outMessage.getPayload(), 2); + + outMessage = remainderIsTwoChannel.receive(0); + + assertEquals(outMessage.getPayload(), 5); + + } + +} diff --git a/spring-integration/src/test/java/com/baeldung/subflows/publishsubscribechannel/PublishSubscribeChannelUnitTest.java b/spring-integration/src/test/java/com/baeldung/subflows/publishsubscribechannel/PublishSubscribeChannelUnitTest.java new file mode 100644 index 0000000000..91bf38c626 --- /dev/null +++ b/spring-integration/src/test/java/com/baeldung/subflows/publishsubscribechannel/PublishSubscribeChannelUnitTest.java @@ -0,0 +1,62 @@ +package com.baeldung.subflows.publishsubscribechannel; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.messaging.Message; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.baeldung.subflows.publishsubscribechannel.PublishSubscibeChannelExample.NumbersClassifier; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PublishSubscibeChannelExample.class }) +public class PublishSubscribeChannelUnitTest { + @Autowired + private QueueChannel multipleofThreeChannel; + + @Autowired + private QueueChannel remainderIsOneChannel; + + @Autowired + private QueueChannel remainderIsTwoChannel; + + @Autowired + private NumbersClassifier numbersClassifier; + + @Test + public void whenSendMessagesToFlow_thenNumbersAreClassified() { + + numbersClassifier.classify(Arrays.asList(1, 2, 3, 4, 5, 6)); + + Message outMessage = multipleofThreeChannel.receive(0); + + assertEquals(outMessage.getPayload(), 3); + + outMessage = multipleofThreeChannel.receive(0); + + assertEquals(outMessage.getPayload(), 6); + + outMessage = remainderIsOneChannel.receive(0); + + assertEquals(outMessage.getPayload(), 1); + outMessage = remainderIsOneChannel.receive(0); + + assertEquals(outMessage.getPayload(), 4); + + outMessage = remainderIsTwoChannel.receive(0); + + assertEquals(outMessage.getPayload(), 2); + + outMessage = remainderIsTwoChannel.receive(0); + + assertEquals(outMessage.getPayload(), 5); + + } + +} diff --git a/spring-integration/src/test/java/com/baeldung/subflows/routetorecipients/RouteToRecipientsUnitTest.java b/spring-integration/src/test/java/com/baeldung/subflows/routetorecipients/RouteToRecipientsUnitTest.java new file mode 100644 index 0000000000..d7a768dcd9 --- /dev/null +++ b/spring-integration/src/test/java/com/baeldung/subflows/routetorecipients/RouteToRecipientsUnitTest.java @@ -0,0 +1,63 @@ +package com.baeldung.subflows.routetorecipients; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.messaging.Message; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.baeldung.subflows.routetorecipients.RouteToRecipientsExample; +import com.baeldung.subflows.routetorecipients.RouteToRecipientsExample.NumbersClassifier; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { RouteToRecipientsExample.class }) +public class RouteToRecipientsUnitTest { + @Autowired + private QueueChannel multipleofThreeChannel; + + @Autowired + private QueueChannel remainderIsOneChannel; + + @Autowired + private QueueChannel remainderIsTwoChannel; + + @Autowired + private NumbersClassifier numbersClassifier; + + @Test + public void whenSendMessagesToFlow_thenNumbersAreClassified() { + + numbersClassifier.classify(Arrays.asList(1, 2, 3, 4, 5, 6)); + + Message outMessage = multipleofThreeChannel.receive(0); + + assertEquals(outMessage.getPayload(), 3); + + outMessage = multipleofThreeChannel.receive(0); + + assertEquals(outMessage.getPayload(), 6); + + outMessage = remainderIsOneChannel.receive(0); + + assertEquals(outMessage.getPayload(), 1); + outMessage = remainderIsOneChannel.receive(0); + + assertEquals(outMessage.getPayload(), 4); + + outMessage = remainderIsTwoChannel.receive(0); + + assertEquals(outMessage.getPayload(), 2); + + outMessage = remainderIsTwoChannel.receive(0); + + assertEquals(outMessage.getPayload(), 5); + + } + +} diff --git a/spring-integration/src/test/java/com/baeldung/subflows/separateflows/SeparateFlowsUnitTest.java b/spring-integration/src/test/java/com/baeldung/subflows/separateflows/SeparateFlowsUnitTest.java new file mode 100644 index 0000000000..c02badcb1a --- /dev/null +++ b/spring-integration/src/test/java/com/baeldung/subflows/separateflows/SeparateFlowsUnitTest.java @@ -0,0 +1,75 @@ +package com.baeldung.subflows.separateflows; + +import java.util.Arrays; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.messaging.Message; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import com.baeldung.subflows.separateflows.SeparateFlowsExample.NumbersClassifier; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { SeparateFlowsExample.class }) +public class SeparateFlowsUnitTest { + @Autowired + private QueueChannel multipleOfThreeChannel; + @Autowired + private QueueChannel remainderIsOneChannel; + @Autowired + private QueueChannel remainderIsTwoChannel; + + @Autowired + private NumbersClassifier numbersClassifier; + + @Test + public void whenSendMessagesToMultipleOf3Flow_thenOutputMultiplesOf3() { + + numbersClassifier.multipleofThree(Arrays.asList(1, 2, 3, 4, 5, 6)); + + Message outMessage = multipleOfThreeChannel.receive(0); + + assertEquals(outMessage.getPayload(), 3); + + outMessage = multipleOfThreeChannel.receive(0); + + assertEquals(outMessage.getPayload(), 6); + outMessage = multipleOfThreeChannel.receive(0); + assertNull(outMessage); + } + + @Test + public void whenSendMessagesToRemainderIs1Flow_thenOutputRemainderIs1() { + + numbersClassifier.remainderIsOne(Arrays.asList(1, 2, 3, 4, 5, 6)); + + Message outMessage = remainderIsOneChannel.receive(0); + + assertEquals(outMessage.getPayload(), 1); + + outMessage = remainderIsOneChannel.receive(0); + + assertEquals(outMessage.getPayload(), 4); + + } + + @Test + public void whenSendMessagesToRemainderIs2Flow_thenOutputRemainderIs2() { + + numbersClassifier.remainderIsTwo(Arrays.asList(1, 2, 3, 4, 5, 6)); + + Message outMessage = remainderIsTwoChannel.receive(0); + + assertEquals(outMessage.getPayload(), 2); + + outMessage = remainderIsTwoChannel.receive(0); + + assertEquals(outMessage.getPayload(), 5); + + } + +} diff --git a/spring-integration/src/test/java/com/baeldung/subflows/subflowmapping/RouterUnitTest.java b/spring-integration/src/test/java/com/baeldung/subflows/subflowmapping/RouterUnitTest.java new file mode 100644 index 0000000000..9ecbb22a9b --- /dev/null +++ b/spring-integration/src/test/java/com/baeldung/subflows/subflowmapping/RouterUnitTest.java @@ -0,0 +1,62 @@ +package com.baeldung.subflows.subflowmapping; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.messaging.Message; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.baeldung.subflows.subflowmapping.RouterExample.NumbersClassifier; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { RouterExample.class }) +public class RouterUnitTest { + @Autowired + private QueueChannel multipleofThreeChannel; + + @Autowired + private QueueChannel remainderIsOneChannel; + + @Autowired + private QueueChannel remainderIsTwoChannel; + + @Autowired + private NumbersClassifier numbersClassifier; + + @Test + public void whenSendMessagesToFlow_thenNumbersAreClassified() { + + numbersClassifier.classify(Arrays.asList(1, 2, 3, 4, 5, 6)); + + Message outMessage = multipleofThreeChannel.receive(0); + + assertEquals(outMessage.getPayload(), 3); + + outMessage = multipleofThreeChannel.receive(0); + + assertEquals(outMessage.getPayload(), 6); + + outMessage = remainderIsOneChannel.receive(0); + + assertEquals(outMessage.getPayload(), 1); + outMessage = remainderIsOneChannel.receive(0); + + assertEquals(outMessage.getPayload(), 4); + + outMessage = remainderIsTwoChannel.receive(0); + + assertEquals(outMessage.getPayload(), 2); + + outMessage = remainderIsTwoChannel.receive(0); + + assertEquals(outMessage.getPayload(), 5); + + } + +} diff --git a/spring-jenkins-pipeline/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-jenkins-pipeline/src/test/java/org/baeldung/SpringContextIntegrationTest.java index 8eb1589de7..0354f7211c 100644 --- a/spring-jenkins-pipeline/src/test/java/org/baeldung/SpringContextIntegrationTest.java +++ b/spring-jenkins-pipeline/src/test/java/org/baeldung/SpringContextIntegrationTest.java @@ -3,12 +3,14 @@ package org.baeldung; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringRunner; import com.baeldung.SpringJenkinsPipelineApplication; @RunWith(SpringRunner.class) @SpringBootTest(classes = SpringJenkinsPipelineApplication.class) +@DirtiesContext public class SpringContextIntegrationTest { @Test diff --git a/spring-mvc-simple/pom.xml b/spring-mvc-simple/pom.xml index bd63b5ed1c..e4e30183eb 100644 --- a/spring-mvc-simple/pom.xml +++ b/spring-mvc-simple/pom.xml @@ -20,10 +20,6 @@ spring-oxm ${spring-oxm.version} - - org.springframework - spring-context-support - com.sun.mail javax.mail diff --git a/spring-mvc-simple/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java index 284be6c212..941a984684 100644 --- a/spring-mvc-simple/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java +++ b/spring-mvc-simple/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java @@ -1,7 +1,9 @@ package com.baeldung.spring.configuration; -import com.baeldung.spring.controller.rss.ArticleRssFeedViewResolver; -import com.baeldung.spring.controller.rss.JsonChannelHttpMessageConverter; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @@ -21,13 +23,12 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; import org.springframework.web.servlet.view.InternalResourceViewResolver; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; +import com.baeldung.spring.controller.rss.ArticleRssFeedViewResolver; +import com.baeldung.spring.controller.rss.JsonChannelHttpMessageConverter; @Configuration @EnableWebMvc -@ComponentScan(basePackages = { "com.baeldung.springmvcforms", "com.baeldung.spring.controller", "com.baeldung.spring.validator", "com.baeldung.spring.mail" }) +@ComponentScan(basePackages = { "com.baeldung.springmvcforms", "com.baeldung.spring.controller", "com.baeldung.spring.validator", "com.baeldung.spring.mail", "com.baeldung.spring.service" }) public class ApplicationConfiguration implements WebMvcConfigurer { @Override diff --git a/spring-mvc-simple/src/main/java/com/baeldung/spring/configuration/PushConfiguration.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/configuration/PushConfiguration.java index 3072501cfa..3aba7e9d89 100644 --- a/spring-mvc-simple/src/main/java/com/baeldung/spring/configuration/PushConfiguration.java +++ b/spring-mvc-simple/src/main/java/com/baeldung/spring/configuration/PushConfiguration.java @@ -8,9 +8,10 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.InternalResourceViewResolver; +// needs HTTP 2 https://github.com/spring-projects/spring-framework/wiki/HTTP-2-support @Configuration @EnableWebMvc -@ComponentScan(basePackages = "com.baeldung.spring.controller.push") +@ComponentScan(basePackages = "com.baeldung.spring.push.controller") public class PushConfiguration implements WebMvcConfigurer { @Bean diff --git a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/RequestParamController.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/RequestParamController.java new file mode 100644 index 0000000000..a9846f1ba9 --- /dev/null +++ b/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/RequestParamController.java @@ -0,0 +1,79 @@ +package com.baeldung.spring.controller; + +import java.util.List; +import java.util.Map; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + + +@Controller +public class RequestParamController { + + @GetMapping("/api/foos") + @ResponseBody + public String getFoos(@RequestParam String id){ + return "ID: " + id; + } + + @PostMapping("/api/foos") + @ResponseBody + public String addFoo(@RequestParam(name = "id") String fooId, @RequestParam String name){ + return "ID: " + fooId; + } + + @GetMapping("/api/foos2") + @ResponseBody + public String getFoos2(@RequestParam(required = false) String id){ + return "ID: " + id; + } + + @GetMapping("/api/foos3") + @ResponseBody + public String getFoos3(@RequestParam(defaultValue = "test") String id){ + return "ID: " + id; + } + + @PostMapping("/api/foos1") + @ResponseBody + public String updateFoos(@RequestParam Map allParams){ + return "Parameters are " + allParams.entrySet(); + } + + @GetMapping("/api/foos4") + @ResponseBody + public String getFoos4(@RequestParam List id){ + return "ID are " + id; + } + + @GetMapping("/foos/{id}") + @ResponseBody + public String getFooById(@PathVariable String id){ + return "ID: " + id; + } + + @GetMapping("/foos") + @ResponseBody + public String getFooByIdUsingQueryParam(@RequestParam String id){ + return "ID: " + id; + } + + @GetMapping({"/myfoos/optional", "/myfoos/optional/{id}"}) + @ResponseBody + public String getFooByOptionalId(@PathVariable(required = false) String id){ + return "ID: " + id; + } + + @GetMapping("/myfoos/optionalParam") + @ResponseBody + public String getFooByOptionalIdUsingQueryParam(@RequestParam(required = false) String id){ + return "ID: " + id; + } + + + +} diff --git a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/push/PushController.java b/spring-mvc-simple/src/main/java/com/baeldung/spring/push/controller/PushController.java similarity index 92% rename from spring-mvc-simple/src/main/java/com/baeldung/spring/controller/push/PushController.java rename to spring-mvc-simple/src/main/java/com/baeldung/spring/push/controller/PushController.java index 88448d4885..e812e5df90 100644 --- a/spring-mvc-simple/src/main/java/com/baeldung/spring/controller/push/PushController.java +++ b/spring-mvc-simple/src/main/java/com/baeldung/spring/push/controller/PushController.java @@ -1,4 +1,4 @@ -package com.baeldung.spring.controller.push; +package com.baeldung.spring.push.controller; import javax.servlet.http.PushBuilder; diff --git a/spring-rest-template/README.md b/spring-rest-template/README.md index d69d5c01c7..2c31796080 100644 --- a/spring-rest-template/README.md +++ b/spring-rest-template/README.md @@ -5,3 +5,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: - [Uploading MultipartFile with Spring RestTemplate](http://www.baeldung.com/spring-rest-template-multipart-upload) +- [Mocking a RestTemplate in Spring](https://www.baeldung.com/spring-mock-rest-template) diff --git a/spring-rest/README.md b/spring-rest/README.md index d449a4d92a..5b8a35a4a5 100644 --- a/spring-rest/README.md +++ b/spring-rest/README.md @@ -23,3 +23,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Using the Spring RestTemplate Interceptor](http://www.baeldung.com/spring-rest-template-interceptor) - [Get and Post Lists of Objects with RestTemplate](http://www.baeldung.com/spring-rest-template-list) - [How to Set a Header on a Response with Spring 5](http://www.baeldung.com/spring-response-header) +- [Spring’s RequestBody and ResponseBody Annotations](https://www.baeldung.com/spring-request-response-body) diff --git a/testing-modules/load-testing-comparison/pom.xml b/testing-modules/load-testing-comparison/pom.xml new file mode 100644 index 0000000000..869eda1bb5 --- /dev/null +++ b/testing-modules/load-testing-comparison/pom.xml @@ -0,0 +1,148 @@ + + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + ../../pom.xml + + 4.0.0 + + load-testing-bakeoff + + + 1.8 + 1.8 + UTF-8 + 2.11.12 + 2.2.5 + 3.2.2 + 2.2.1 + 5.0 + 3.11 + 2.0.5.RELEASE + + + + + io.gatling + gatling-app + ${gatling.version} + + + io.gatling + gatling-recorder + ${gatling.version} + + + io.gatling.highcharts + gatling-charts-highcharts + ${gatling.version} + + + org.scala-lang + scala-library + ${scala.version} + + + + + + + + com.fasterxml.jackson.core + jackson-databind + 2.9.4 + + + org.springframework.boot + spring-boot-starter + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-data-jpa + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-test + ${spring.boot.version} + test + + + com.h2database + h2 + 1.4.197 + + + org.projectlombok + lombok + 1.18.2 + compile + + + + + + + + + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.0.5.RELEASE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/Application.java b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/Application.java new file mode 100644 index 0000000000..6647bcb640 --- /dev/null +++ b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/Application.java @@ -0,0 +1,12 @@ +package com.baeldung.loadtesting; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/RewardsController.java b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/RewardsController.java new file mode 100644 index 0000000000..50cc6fb7ab --- /dev/null +++ b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/RewardsController.java @@ -0,0 +1,51 @@ +package com.baeldung.loadtesting; + +import com.baeldung.loadtesting.model.CustomerRewardsAccount; +import com.baeldung.loadtesting.model.Transaction; +import com.baeldung.loadtesting.repository.CustomerRewardsRepository; +import com.baeldung.loadtesting.repository.TransactionRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Calendar; +import java.util.List; +import java.util.Optional; + +@RestController +public class RewardsController { + + @Autowired + private CustomerRewardsRepository customerRewardsRepository; + + @Autowired + private TransactionRepository transactionRepository; + + @PostMapping(path="/transactions/add") + public @ResponseBody Transaction saveTransactions(@RequestBody Transaction trnsctn){ + trnsctn.setTransactionDate(Calendar.getInstance().getTime()); + Transaction result = transactionRepository.save(trnsctn); + return result; + } + + @GetMapping(path="/transactions/findAll/{rewardId}") + public @ResponseBody Iterable getTransactions(@PathVariable Integer rewardId){ + return transactionRepository.findByCustomerRewardsId(rewardId); + } + + @PostMapping(path="/rewards/add") + public @ResponseBody CustomerRewardsAccount addRewardsAcount(@RequestBody CustomerRewardsAccount body) { + Optional acct = customerRewardsRepository.findByCustomerId(body.getCustomerId()); + return !acct.isPresent() ? customerRewardsRepository.save(body) : acct.get(); + } + + @GetMapping(path="/rewards/find/{customerId}") + public @ResponseBody + Optional find(@PathVariable Integer customerId) { + return customerRewardsRepository.findByCustomerId(customerId); + } + + @GetMapping(path="/rewards/all") + public @ResponseBody List findAll() { + return customerRewardsRepository.findAll(); + } +} diff --git a/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/TransactionController.java b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/TransactionController.java new file mode 100644 index 0000000000..2ea2c06a41 --- /dev/null +++ b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/TransactionController.java @@ -0,0 +1,26 @@ +package com.baeldung.loadtesting; + +import com.baeldung.loadtesting.model.Transaction; +import com.baeldung.loadtesting.repository.TransactionRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@Deprecated +public class TransactionController { + + @Autowired + private TransactionRepository transactionRepository; + + @PostMapping(path="/addTransaction") + public @ResponseBody + String saveTransactions(@RequestBody Transaction trnsctn){ + transactionRepository.save(trnsctn); + return "Saved Transaction."; + } + + @GetMapping(path="/findAll/{rewardId}") + public @ResponseBody Iterable getTransactions(@RequestParam Integer id){ + return transactionRepository.findByCustomerRewardsId(id); + } +} diff --git a/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/model/CustomerRewardsAccount.java b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/model/CustomerRewardsAccount.java new file mode 100644 index 0000000000..2c6742fbaf --- /dev/null +++ b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/model/CustomerRewardsAccount.java @@ -0,0 +1,22 @@ +package com.baeldung.loadtesting.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +import lombok.Data; + +@Entity +@Data +public class CustomerRewardsAccount { + + @Id + @GeneratedValue(strategy= GenerationType.AUTO) + private Integer id; + private Integer customerId; + + public Integer getCustomerId(){ + return this.customerId; + } +} diff --git a/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/model/Transaction.java b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/model/Transaction.java new file mode 100644 index 0000000000..312f52f4ab --- /dev/null +++ b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/model/Transaction.java @@ -0,0 +1,30 @@ +package com.baeldung.loadtesting.model; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import java.util.Date; +import java.util.Calendar; + +@Entity +@Data +public class Transaction { + + @Id + @GeneratedValue(strategy= GenerationType.AUTO) + private Integer id; + private Integer customerRewardsId; + private Integer customerId; + private Date transactionDate; + + public Transaction(){ + transactionDate = Calendar.getInstance().getTime(); + } + + public void setTransactionDate(Date transactionDate){ + this.transactionDate = transactionDate; + } +} diff --git a/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/repository/CustomerRewardsRepository.java b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/repository/CustomerRewardsRepository.java new file mode 100644 index 0000000000..f945359eb8 --- /dev/null +++ b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/repository/CustomerRewardsRepository.java @@ -0,0 +1,11 @@ +package com.baeldung.loadtesting.repository; + +import com.baeldung.loadtesting.model.CustomerRewardsAccount; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface CustomerRewardsRepository extends JpaRepository { + + Optional findByCustomerId(Integer customerId); +} diff --git a/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/repository/TransactionRepository.java b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/repository/TransactionRepository.java new file mode 100644 index 0000000000..af0b343c10 --- /dev/null +++ b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/repository/TransactionRepository.java @@ -0,0 +1,11 @@ +package com.baeldung.loadtesting.repository; + +import com.baeldung.loadtesting.model.Transaction; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface TransactionRepository extends JpaRepository { + + List findByCustomerRewardsId(Integer rewardsId); +} diff --git a/testing-modules/load-testing-comparison/src/main/resources/scripts/Gatling/GatlingScenario.scala b/testing-modules/load-testing-comparison/src/main/resources/scripts/Gatling/GatlingScenario.scala new file mode 100644 index 0000000000..f9b3837759 --- /dev/null +++ b/testing-modules/load-testing-comparison/src/main/resources/scripts/Gatling/GatlingScenario.scala @@ -0,0 +1,52 @@ +package com.baeldung + +import scala.util._ +import io.gatling.core.Predef._ +import io.gatling.http.Predef._ +import scala.concurrent.duration._ + +class RewardsScenario extends Simulation { + + def randCustId() = Random.nextInt(99) + + val httpProtocol = http.baseUrl("http://localhost:8080") + .acceptHeader("text/html,application/json;q=0.9,*/*;q=0.8") + .doNotTrackHeader("1") + .acceptLanguageHeader("en-US,en;q=0.5") + .acceptEncodingHeader("gzip, deflate") + .userAgentHeader("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0") + + val scn = scenario("RewardsScenario") + .repeat(10){ + exec(http("transactions_add") + .post("/transactions/add/") + .body(StringBody("""{ "customerRewardsId":null,"customerId":""""+ randCustId() + """","transactionDate":null }""")).asJson + .check(jsonPath("$.id").saveAs("txnId")) + .check(jsonPath("$.transactionDate").saveAs("txtDate")) + .check(jsonPath("$.customerId").saveAs("custId"))) + .pause(1) + + .exec(http("get_reward") + .get("/rewards/find/${custId}") + .check(jsonPath("$.id").saveAs("rwdId"))) + .pause(1) + + .doIf("${rwdId.isUndefined()}"){ + exec(http("rewards_add") + .post("/rewards/add") + .body(StringBody("""{ "customerId": "${custId}" }""")).asJson + .check(jsonPath("$.id").saveAs("rwdId"))) + } + + .exec(http("transactions_add") + .post("/transactions/add/") + .body(StringBody("""{ "customerRewardsId":"${rwdId}","customerId":"${custId}","transactionDate":"${txtDate}" }""")).asJson) + .pause(1) + + .exec(http("get_reward") + .get("/transactions/findAll/${rwdId}")) + } + setUp( + scn.inject(atOnceUsers(100)) + ).protocols(httpProtocol) +} \ No newline at end of file diff --git a/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx b/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx new file mode 100644 index 0000000000..da32a13a22 --- /dev/null +++ b/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx @@ -0,0 +1,293 @@ + + + + + + false + true + false + + + + + + + + continue + + false + 10 + + 100 + 0 + false + + + + + + true + 1 + + + + + + Content-Type + application/json + + + + + + true + + + + false + {"customerRewardsId":null,"customerId":${random},"transactionDate":null} + = + + + + localhost + 8080 + http + + /transactions/add + POST + true + false + true + false + + + + + + + txnId + $.id + 1 + all + foo + + + + txnDate + $.transactionDate + 1 + Never + + + + custId + $.customerId + 1 + all + bob + + + + + + + + localhost + 8080 + + + /rewards/find/${custId} + GET + true + false + true + false + + + + + + + rwdId + $.id + 1 + 0 + all + + + + + ${rwdId} == 0 + true + + + + true + + + + false + {"customerId":${custId}} + = + + + + localhost + 8080 + + + /rewards/add + POST + true + false + true + false + + + + + + + rwdId + $.id + 1 + bar + all + + + + + + true + + + + false + {"id":${txnId},"customerRewardsId":${rwdId},"customerId":${custId},"transactionDate":"${txnDate}"} + = + + + + localhost + 8080 + + + /transactions/add + POST + true + false + true + false + + + + + + + + + + localhost + 8080 + + + /transactions/findAll/${rwdId} + GET + true + false + true + false + + + + + + + + 10000 + 1 + + false + 67 + random + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + + diff --git a/testing-modules/load-testing-comparison/src/main/resources/scripts/The Grinder/grinder.properties b/testing-modules/load-testing-comparison/src/main/resources/scripts/The Grinder/grinder.properties new file mode 100644 index 0000000000..68adf90856 --- /dev/null +++ b/testing-modules/load-testing-comparison/src/main/resources/scripts/The Grinder/grinder.properties @@ -0,0 +1,5 @@ +grinder.script = grinder.py +grinder.threads = 100 +grinder.processes = 1 +grinder.runs = 10 +grinder.logDirectory = /logs diff --git a/testing-modules/load-testing-comparison/src/main/resources/scripts/The Grinder/grinder.py b/testing-modules/load-testing-comparison/src/main/resources/scripts/The Grinder/grinder.py new file mode 100644 index 0000000000..025f90d38b --- /dev/null +++ b/testing-modules/load-testing-comparison/src/main/resources/scripts/The Grinder/grinder.py @@ -0,0 +1,40 @@ +import java.util.Random +from net.grinder.script import Test +from net.grinder.script.Grinder import grinder +from net.grinder.plugin.http import HTTPRequest, HTTPPluginControl, HTTPUtilities +from HTTPClient import NVPair + +def parseJsonString(json, element): + for x in json.split(","): + pc = x.replace('"','').split(":") + if pc[0].replace("{","") == element: + ele = pc[1].replace("}","") + return ele + else: + return "" + +test1 = Test(1, "Request resource") +request1 = HTTPRequest() +headers = \ +( NVPair('Content-Type', 'application/json'), ) +request1.setHeaders(headers) +utilities = HTTPPluginControl.getHTTPUtilities() +test1.record(request1) +random=java.util.Random() + +class TestRunner: + def __call__(self): + customerId = str(random.nextInt()); + + result = request1.POST("http://localhost:8080/transactions/add", "{"'"customerRewardsId"'":null,"'"customerId"'":"+ customerId + ","'"transactionDate"'":null}") + txnId = parseJsonString(result.getText(), "id") + + result = request1.GET("http://localhost:8080/rewards/find/"+ customerId) + rwdId = parseJsonString(result.getText(), "id") + + if rwdId == "": + result = request1.POST("http://localhost:8080/rewards/add", "{"'"customerId"'":"+ customerId + "}") + rwdId = parseJsonString(result.getText(), "id") + + result = request1.POST("http://localhost:8080/transactions/add", "{"'"id"'":" + txnId + ","'"customerRewardsId"'":" + rwdId + ","'"customerId"'":"+ customerId + ","'"transactionDate"'":null}") + result = request1.GET("http://localhost:8080/transactions/findAll/" + rwdId) \ No newline at end of file diff --git a/testing-modules/spring-testing/src/main/java/org/baeldung/reflectiontestutils/repository/Employee.java b/testing-modules/spring-testing/src/main/java/org/baeldung/reflectiontestutils/repository/Employee.java new file mode 100644 index 0000000000..0677b05d66 --- /dev/null +++ b/testing-modules/spring-testing/src/main/java/org/baeldung/reflectiontestutils/repository/Employee.java @@ -0,0 +1,23 @@ +package org.baeldung.reflectiontestutils.repository; + +public class Employee { + private Integer id; + private String name; + + public Integer getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + private String employeeToString() { + return "id: " + getId() + "; name: " + getName(); + } + +} diff --git a/testing-modules/spring-testing/src/main/java/org/baeldung/reflectiontestutils/repository/EmployeeService.java b/testing-modules/spring-testing/src/main/java/org/baeldung/reflectiontestutils/repository/EmployeeService.java new file mode 100644 index 0000000000..699ec3236c --- /dev/null +++ b/testing-modules/spring-testing/src/main/java/org/baeldung/reflectiontestutils/repository/EmployeeService.java @@ -0,0 +1,14 @@ +package org.baeldung.reflectiontestutils.repository; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class EmployeeService { + @Autowired + private HRService hrService; + + public String findEmployeeStatus(Integer employeeId) { + return "Employee " + employeeId + " status: " + hrService.getEmployeeStatus(employeeId); + } +} diff --git a/testing-modules/spring-testing/src/main/java/org/baeldung/reflectiontestutils/repository/HRService.java b/testing-modules/spring-testing/src/main/java/org/baeldung/reflectiontestutils/repository/HRService.java new file mode 100644 index 0000000000..e693aca764 --- /dev/null +++ b/testing-modules/spring-testing/src/main/java/org/baeldung/reflectiontestutils/repository/HRService.java @@ -0,0 +1,11 @@ +package org.baeldung.reflectiontestutils.repository; + +import org.springframework.stereotype.Component; + +@Component +public class HRService { + + public String getEmployeeStatus(Integer employeeId) { + return "Inactive"; + } +} diff --git a/testing-modules/spring-testing/src/test/java/org/baeldung/reflectiontestutils/ReflectionTestUtilsUnitTest.java b/testing-modules/spring-testing/src/test/java/org/baeldung/reflectiontestutils/ReflectionTestUtilsUnitTest.java new file mode 100644 index 0000000000..64c7ca19ef --- /dev/null +++ b/testing-modules/spring-testing/src/test/java/org/baeldung/reflectiontestutils/ReflectionTestUtilsUnitTest.java @@ -0,0 +1,46 @@ +package org.baeldung.reflectiontestutils; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; + +import org.baeldung.reflectiontestutils.repository.Employee; +import org.baeldung.reflectiontestutils.repository.EmployeeService; +import org.baeldung.reflectiontestutils.repository.HRService; +import org.junit.Test; +import org.springframework.test.util.ReflectionTestUtils; + +import static org.mockito.Mockito.when; + +public class ReflectionTestUtilsUnitTest { + + @Test + public void whenNonPublicField_thenReflectionTestUtilsSetField() { + Employee employee = new Employee(); + ReflectionTestUtils.setField(employee, "id", 1); + assertTrue(employee.getId().equals(1)); + + } + + @Test + public void whenNonPublicMethod_thenReflectionTestUtilsInvokeMethod() { + Employee employee = new Employee(); + ReflectionTestUtils.setField(employee, "id", 1); + employee.setName("Smith, John"); + assertTrue(ReflectionTestUtils.invokeMethod(employee, "employeeToString").equals("id: 1; name: Smith, John")); + } + + @Test + public void whenInjectingMockOfDependency_thenReflectionTestUtilsSetField() { + Employee employee = new Employee(); + ReflectionTestUtils.setField(employee, "id", 1); + employee.setName("Smith, John"); + + HRService hrService = mock(HRService.class); + when(hrService.getEmployeeStatus(employee.getId())).thenReturn("Active"); + EmployeeService employeeService = new EmployeeService(); + + // Inject mock into the private field + ReflectionTestUtils.setField(employeeService, "hrService", hrService); + assertEquals("Employee " + employee.getId() + " status: Active", employeeService.findEmployeeStatus(employee.getId())); + } +}