diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/FoldingHash.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/FoldingHash.java new file mode 100644 index 0000000000..0ea128c1d9 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/FoldingHash.java @@ -0,0 +1,78 @@ +package com.baeldung.folding; + +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * Calculate a hash value for the strings using the folding technique. + * + * The implementation serves only to the illustration purposes and is far + * from being the most efficient. + * + * @author A.Shcherbakov + * + */ +public class FoldingHash { + + /** + * Calculate the hash value of a given string. + * + * @param str Assume it is not null + * @param groupSize the group size in the folding technique + * @param maxValue defines a max value that the hash may acquire (exclusive) + * @return integer value from 0 (inclusive) to maxValue (exclusive) + */ + public int hash(String str, int groupSize, int maxValue) { + final int[] codes = this.toAsciiCodes(str); + return IntStream.range(0, str.length()) + .filter(i -> i % groupSize == 0) + .mapToObj(i -> extract(codes, i, groupSize)) + .map(block -> concatenate(block)) + .reduce(0, (a, b) -> (a + b) % maxValue); + } + + /** + * Returns a new array of given length whose elements are take from + * the original one starting from the offset. + * + * If the original array has not enough elements, the returning array will contain + * element from the offset till the end of the original array. + * + * @param numbers original array. Assume it is not null. + * @param offset index of the element to start from. Assume it is less than the size of the array + * @param length max size of the resulting array + * @return + */ + public int[] extract(int[] numbers, int offset, int length) { + final int defect = numbers.length - (offset + length); + final int s = defect < 0 ? length + defect : length; + int[] result = new int[s]; + for (int index = 0; index < s; index++) { + result[index] = numbers[index + offset]; + } + return result; + } + + /** + * Concatenate the numbers into a single number as if they were strings. + * Assume that the procedure does not suffer from the overflow. + * @param numbers integers to concatenate + * @return + */ + public int concatenate(int[] numbers) { + final String merged = IntStream.of(numbers) + .mapToObj(number -> "" + number) + .collect(Collectors.joining()); + return Integer.parseInt(merged, 10); + } + + /** + * Convert the string into its characters' ASCII codes. + * @param str input string + * @return + */ + private int[] toAsciiCodes(String str) { + return str.chars() + .toArray(); + } +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/Main.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/Main.java new file mode 100644 index 0000000000..3b055a0dbe --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/Main.java @@ -0,0 +1,17 @@ +package com.baeldung.folding; + +/** + * Code snippet for article "A Guide to the Folding Technique". + * + * @author A.Shcherbakov + * + */ +public class Main { + + public static void main(String... arg) { + FoldingHash hasher = new FoldingHash(); + final String str = "Java language"; + System.out.println(hasher.hash(str, 2, 100_000)); + System.out.println(hasher.hash(str, 3, 1_000)); + } +} diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/folding/FoldingHashUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/folding/FoldingHashUnitTest.java new file mode 100644 index 0000000000..43e33d8378 --- /dev/null +++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/folding/FoldingHashUnitTest.java @@ -0,0 +1,54 @@ +package com.baeldung.folding; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class FoldingHashUnitTest { + + @Test + public void givenStringJavaLanguage_whenSize2Capacity100000_then48933() throws Exception { + final FoldingHash hasher = new FoldingHash(); + final int value = hasher.hash("Java language", 2, 100_000); + assertEquals(value, 48933); + } + + @Test + public void givenStringVaJaLanguage_whenSize2Capacity100000_thenSameAsJavaLanguage() throws Exception { + final FoldingHash hasher = new FoldingHash(); + final int java = hasher.hash("Java language", 2, 100_000); + final int vaja = hasher.hash("vaJa language", 2, 100_000); + assertTrue(java == vaja); + } + + @Test + public void givenSingleElementArray_whenOffset0Size2_thenSingleElement() throws Exception { + final FoldingHash hasher = new FoldingHash(); + final int[] value = hasher.extract(new int[] { 5 }, 0, 2); + assertArrayEquals(new int[] { 5 }, value); + } + + @Test + public void givenFiveElementArray_whenOffset0Size3_thenFirstThreeElements() throws Exception { + final FoldingHash hasher = new FoldingHash(); + final int[] value = hasher.extract(new int[] { 1, 2, 3, 4, 5 }, 0, 3); + assertArrayEquals(new int[] { 1, 2, 3 }, value); + } + + @Test + public void givenFiveElementArray_whenOffset1Size2_thenTwoElements() throws Exception { + final FoldingHash hasher = new FoldingHash(); + final int[] value = hasher.extract(new int[] { 1, 2, 3, 4, 5 }, 1, 2); + assertArrayEquals(new int[] { 2, 3 }, value); + } + + @Test + public void givenFiveElementArray_whenOffset2SizeTooBig_thenElementsToTheEnd() throws Exception { + final FoldingHash hasher = new FoldingHash(); + final int[] value = hasher.extract(new int[] { 1, 2, 3, 4, 5 }, 2, 2000); + assertArrayEquals(new int[] { 3, 4, 5 }, value); + } + +} diff --git a/autovalue/pom.xml b/autovalue/pom.xml index 3ec2d26b35..a10e8ef055 100644 --- a/autovalue/pom.xml +++ b/autovalue/pom.xml @@ -29,6 +29,12 @@ + + com.google.auto.service + auto-service + ${auto-service.version} + true + com.google.inject @@ -40,6 +46,7 @@ 1.3 1.0-beta5 + 1.0-rc5 4.2.0 diff --git a/autovalue/src/main/java/com/baeldung/autoservice/BingTranslationServiceProvider.java b/autovalue/src/main/java/com/baeldung/autoservice/BingTranslationServiceProvider.java new file mode 100644 index 0000000000..86d42e80fa --- /dev/null +++ b/autovalue/src/main/java/com/baeldung/autoservice/BingTranslationServiceProvider.java @@ -0,0 +1,14 @@ +package com.baeldung.autoservice; + +import com.google.auto.service.AutoService; + +import java.util.Locale; + +@AutoService(TranslationService.class) +public class BingTranslationServiceProvider implements TranslationService { + @Override + public String translate(String message, Locale from, Locale to) { + // implementation details + return message + " (translated by Bing)"; + } +} diff --git a/autovalue/src/main/java/com/baeldung/autoservice/GoogleTranslationServiceProvider.java b/autovalue/src/main/java/com/baeldung/autoservice/GoogleTranslationServiceProvider.java new file mode 100644 index 0000000000..0bf91ee5ec --- /dev/null +++ b/autovalue/src/main/java/com/baeldung/autoservice/GoogleTranslationServiceProvider.java @@ -0,0 +1,14 @@ +package com.baeldung.autoservice; + +import com.google.auto.service.AutoService; + +import java.util.Locale; + +@AutoService(TranslationService.class) +public class GoogleTranslationServiceProvider implements TranslationService { + @Override + public String translate(String message, Locale from, Locale to) { + // implementation details + return message + " (translated by Google)"; + } +} diff --git a/autovalue/src/main/java/com/baeldung/autoservice/TranslationService.java b/autovalue/src/main/java/com/baeldung/autoservice/TranslationService.java new file mode 100644 index 0000000000..580db46cd1 --- /dev/null +++ b/autovalue/src/main/java/com/baeldung/autoservice/TranslationService.java @@ -0,0 +1,7 @@ +package com.baeldung.autoservice; + +import java.util.Locale; + +public interface TranslationService { + String translate(String message, Locale from, Locale to); +} \ No newline at end of file diff --git a/autovalue/src/test/java/com/baeldung/autoservice/TranslationServiceUnitTest.java b/autovalue/src/test/java/com/baeldung/autoservice/TranslationServiceUnitTest.java new file mode 100644 index 0000000000..9e1bd6d291 --- /dev/null +++ b/autovalue/src/test/java/com/baeldung/autoservice/TranslationServiceUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.autoservice; + +import com.baeldung.autoservice.TranslationService; +import org.junit.Before; +import org.junit.Test; + +import java.util.ServiceLoader; +import java.util.stream.StreamSupport; + +import static org.junit.Assert.assertEquals; + +public class TranslationServiceUnitTest { + + private ServiceLoader loader; + + @Before + public void setUp() { + loader = ServiceLoader.load(TranslationService.class); + } + + @Test + public void whenServiceLoaderLoads_thenLoadsAllProviders() { + long count = StreamSupport.stream(loader.spliterator(), false).count(); + assertEquals(2, count); + } + + @Test + public void whenServiceLoaderLoadsGoogleService_thenGoogleIsLoaded() { + TranslationService googleService = StreamSupport.stream(loader.spliterator(), false) + .filter(p -> p.getClass().getSimpleName().equals("GoogleTranslationServiceProvider")) + .findFirst() + .get(); + + String message = "message"; + assertEquals(message + " (translated by Google)", googleService.translate(message, null, null)); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-8-2/src/main/java/com/baeldung/stream/SkipLimitComparison.java b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/stream/SkipLimitComparison.java new file mode 100644 index 0000000000..65f12ada45 --- /dev/null +++ b/core-java-modules/core-java-8-2/src/main/java/com/baeldung/stream/SkipLimitComparison.java @@ -0,0 +1,46 @@ +package com.baeldung.stream; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class SkipLimitComparison { + + public static void main(String[] args) { + skipExample(); + limitExample(); + limitInfiniteStreamExample(); + getEvenNumbers(10, 10).stream() + .forEach(System.out::println); + } + + public static void skipExample() { + Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + .filter(i -> i % 2 == 0) + .skip(2) + .forEach(i -> System.out.print(i + " ")); + } + + public static void limitExample() { + Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + .filter(i -> i % 2 == 0) + .limit(2) + .forEach(i -> System.out.print(i + " ")); + } + + public static void limitInfiniteStreamExample() { + Stream.iterate(0, i -> i + 1) + .filter(i -> i % 2 == 0) + .limit(10) + .forEach(System.out::println); + } + + private static List getEvenNumbers(int offset, int limit) { + return Stream.iterate(0, i -> i + 1) + .filter(i -> i % 2 == 0) + .skip(offset) + .limit(limit) + .collect(Collectors.toList()); + } + +} diff --git a/core-java-modules/core-java-8/src/main/java/com/baeldung/forEach/ReverseList.java b/core-java-modules/core-java-8/src/main/java/com/baeldung/forEach/ReverseList.java new file mode 100644 index 0000000000..b2ce77a9f6 --- /dev/null +++ b/core-java-modules/core-java-8/src/main/java/com/baeldung/forEach/ReverseList.java @@ -0,0 +1,84 @@ +package com.baeldung.forEach; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.function.Consumer; + +class ReverseList extends ArrayList { + + List list = Arrays.asList("A", "B", "C", "D"); + + Consumer removeElement = s -> { + System.out.println(s + " " + list.size()); + if (s != null && s.equals("A")) { + list.remove("D"); + } + }; + + @Override + public Iterator iterator() { + + final int startIndex = this.size() - 1; + final List list = this; + return new Iterator() { + + int currentIndex = startIndex; + + @Override + public boolean hasNext() { + return currentIndex >= 0; + } + + @Override + public String next() { + String next = list.get(currentIndex); + currentIndex--; + return next; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + public void forEach(Consumer action) { + for (String s : this) { + action.accept(s); + } + } + + public void iterateParallel() { + list.forEach(System.out::print); + System.out.print(" "); + list.parallelStream().forEach(System.out::print); + } + + public void iterateReverse() { + List myList = new ReverseList(); + myList.addAll(list); + myList.forEach(System.out::print); + System.out.print(" "); + myList.stream().forEach(System.out::print); + } + + public void removeInCollectionForEach() { + list.forEach(removeElement); + } + + public void removeInStreamForEach() { + list.stream().forEach(removeElement); + } + + public static void main(String[] argv) { + + ReverseList collectionForEach = new ReverseList(); + collectionForEach.iterateParallel(); + collectionForEach.iterateReverse(); + collectionForEach.removeInCollectionForEach(); + collectionForEach.removeInStreamForEach(); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions/pom.xml b/core-java-modules/core-java-exceptions/pom.xml index 51c4e51341..37f65882c3 100644 --- a/core-java-modules/core-java-exceptions/pom.xml +++ b/core-java-modules/core-java-exceptions/pom.xml @@ -1,26 +1,35 @@ - 4.0.0 - com.baeldung.exception.numberformat - core-java-exceptions - 0.0.1-SNAPSHOT - core-java-exceptions + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + com.baeldung.exception.numberformat + core-java-exceptions + 0.0.1-SNAPSHOT + core-java-exceptions - - com.baeldung - parent-java - 0.0.1-SNAPSHOT - ../../parent-java - + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../../parent-java + - - - junit - junit - 4.12 - test - - + + 3.9 + + + + + junit + junit + 4.12 + test + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/exceptions/RootCauseFinder.java b/core-java-modules/core-java-exceptions/src/main/java/com/baeldung/exceptions/RootCauseFinder.java similarity index 100% rename from core-java-modules/core-java/src/main/java/com/baeldung/exceptions/RootCauseFinder.java rename to core-java-modules/core-java-exceptions/src/main/java/com/baeldung/exceptions/RootCauseFinder.java diff --git a/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exception/error/ErrorGeneratorUnitTest.java b/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exception/error/ErrorGeneratorUnitTest.java index de56fb7113..6dcd0d72e0 100644 --- a/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exception/error/ErrorGeneratorUnitTest.java +++ b/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exception/error/ErrorGeneratorUnitTest.java @@ -1,7 +1,6 @@ -package com.baeldung.error; +package com.baeldung.exception.error; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; public class ErrorGeneratorUnitTest { diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/exceptions/RootCauseFinderUnitTest.java b/core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exceptions/RootCauseFinderUnitTest.java similarity index 100% rename from core-java-modules/core-java/src/test/java/com/baeldung/exceptions/RootCauseFinderUnitTest.java rename to core-java-modules/core-java-exceptions/src/test/java/com/baeldung/exceptions/RootCauseFinderUnitTest.java diff --git a/core-java-modules/core-java-lambdas/README.MD b/core-java-modules/core-java-lambdas/README.MD deleted file mode 100644 index 31790ffbb1..0000000000 --- a/core-java-modules/core-java-lambdas/README.MD +++ /dev/null @@ -1,3 +0,0 @@ -### Relevant Articles - -- [Why Do Local Variables Used in Lambdas Have to Be Final or Effectively Final?](https://www.baeldung.com/java-lambda-effectively-final-local-variables) diff --git a/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/rawtype/RawTypeDemo.java b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/rawtype/RawTypeDemo.java new file mode 100644 index 0000000000..e358219d24 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-2/src/main/java/com/baeldung/rawtype/RawTypeDemo.java @@ -0,0 +1,25 @@ +package com.baeldung.rawtype; + +import java.util.ArrayList; +import java.util.List; + +public class RawTypeDemo { + + public static void main(String[] args) { + RawTypeDemo rawTypeDemo = new RawTypeDemo(); + rawTypeDemo.methodA(); + } + + public void methodA() { + // parameterized type + List listStr = new ArrayList<>(); + listStr.add("Hello Folks!"); + methodB(listStr); + String s = listStr.get(1); // ClassCastException at run time + } + + public void methodB(List rawList) { // Inexpressive raw type + rawList.add(1); // Unsafe operation + } + +} diff --git a/java-collections-conversions/src/test/java/com/baeldung/convertiteratortolist/ConvertIteratorToListServiceUnitTest.java b/java-collections-conversions/src/test/java/com/baeldung/convertiteratortolist/ConvertIteratorToListServiceUnitTest.java new file mode 100644 index 0000000000..4d6cba7d27 --- /dev/null +++ b/java-collections-conversions/src/test/java/com/baeldung/convertiteratortolist/ConvertIteratorToListServiceUnitTest.java @@ -0,0 +1,100 @@ +package com.baeldung.convertiteratortolist; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +import org.apache.commons.collections4.IteratorUtils; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; + +public class ConvertIteratorToListServiceUnitTest { + + Iterator iterator; + + @Before + public void setUp() throws Exception { + iterator = Arrays.asList(1, 2, 3) + .iterator(); + } + + @Test + public void givenAnIterator_whenConvertIteratorToListUsingWhileLoop_thenReturnAList() { + + List actualList = new ArrayList(); + + // Convert Iterator to List using while loop dsf + while (iterator.hasNext()) { + actualList.add(iterator.next()); + } + + assertThat(actualList, hasSize(3)); + assertThat(actualList, containsInAnyOrder(1, 2, 3)); + } + + @Test + public void givenAnIterator_whenConvertIteratorToListAfterJava8_thenReturnAList() { + List actualList = new ArrayList(); + + // Convert Iterator to List using Java 8 + iterator.forEachRemaining(actualList::add); + + assertThat(actualList, hasSize(3)); + assertThat(actualList, containsInAnyOrder(1, 2, 3)); + } + + @Test + public void givenAnIterator_whenConvertIteratorToListJava8Stream_thenReturnAList() { + + // Convert iterator to iterable + Iterable iterable = () -> iterator; + + // Extract List from stream + List actualList = StreamSupport + .stream(iterable.spliterator(), false) + .collect(Collectors.toList()); + + assertThat(actualList, hasSize(3)); + assertThat(actualList, containsInAnyOrder(1, 2, 3)); + } + + @Test + public void givenAnIterator_whenConvertIteratorToImmutableListWithGuava_thenReturnAList() { + + // Convert Iterator to an Immutable list using Guava library in Java + List actualList = ImmutableList.copyOf(iterator); + + assertThat(actualList, hasSize(3)); + assertThat(actualList, containsInAnyOrder(1, 2, 3)); + } + + @Test + public void givenAnIterator_whenConvertIteratorToMutableListWithGuava_thenReturnAList() { + + // Convert Iterator to a mutable list using Guava library in Java + List actualList = Lists.newArrayList(iterator); + + assertThat(actualList, hasSize(3)); + assertThat(actualList, containsInAnyOrder(1, 2, 3)); + } + + @Test + public void givenAnIterator_whenConvertIteratorToMutableListWithApacheCommons_thenReturnAList() { + + // Convert Iterator to a mutable list using Apache Commons library in Java + List actualList = IteratorUtils.toList(iterator); + + assertThat(actualList, hasSize(3)); + assertThat(actualList, containsInAnyOrder(1, 2, 3)); + } +} diff --git a/java-streams/src/test/java/com/baeldung/intstreams/conversion/IntStreamsConversionsUnitTest.java b/java-streams/src/test/java/com/baeldung/intstreams/conversion/IntStreamsConversionsUnitTest.java new file mode 100644 index 0000000000..6cd773e634 --- /dev/null +++ b/java-streams/src/test/java/com/baeldung/intstreams/conversion/IntStreamsConversionsUnitTest.java @@ -0,0 +1,40 @@ +package com.baeldung.intstreams.conversion; + +import org.junit.Test; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import static org.assertj.core.api.Assertions.assertThat; + +public class IntStreamsConversionsUnitTest { + + @Test + public void intStreamToArray() { + int[] first50EvenNumbers = IntStream.iterate(0, i -> i + 2) + .limit(50) + .toArray(); + + assertThat(first50EvenNumbers).hasSize(50); + assertThat(first50EvenNumbers[2]).isEqualTo(4); + } + + @Test + public void intStreamToList() { + List first50IntegerNumbers = IntStream.range(0, 50) + .boxed() + .collect(Collectors.toList()); + + assertThat(first50IntegerNumbers).hasSize(50); + assertThat(first50IntegerNumbers.get(2)).isEqualTo(2); + } + + @Test + public void intStreamToString() { + String first3numbers = IntStream.of(0, 1, 2) + .mapToObj(String::valueOf) + .collect(Collectors.joining(", ", "[", "]")); + + assertThat(first3numbers).isEqualTo("[0, 1, 2]"); + } +} diff --git a/libraries-2/pom.xml b/libraries-2/pom.xml index 53a0233cdd..859de10f13 100644 --- a/libraries-2/pom.xml +++ b/libraries-2/pom.xml @@ -1,113 +1,156 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - 4.0.0 - libraries2 - libraries2 + 4.0.0 + libraries2 + libraries2 - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + - - - jboss-public-repository-group - JBoss Public Repository Group - http://repository.jboss.org/nexus/content/groups/public/ - - true - never - - - true - daily - - - + + + jboss-public-repository-group + JBoss Public Repository Group + http://repository.jboss.org/nexus/content/groups/public/ + + true + never + + + true + daily + + + - + + + org.assertj + assertj-core + ${assertj.version} + + + io.github.classgraph + classgraph + ${classgraph.version} + + + org.jbpm + jbpm-test + ${jbpm.version} + + + info.picocli + picocli + ${picocli.version} + - org.assertj - assertj-core - ${assertj.version} + org.ejml + ejml-all + ${ejml.version} + + + org.nd4j + nd4j-native + ${nd4j.version} + + + org.la4j + la4j + ${la4j.version} - io.github.classgraph - classgraph - ${classgraph.version} - - - org.jbpm - jbpm-test - ${jbpm.version} - - - info.picocli - picocli - ${picocli.version} - - - org.springframework.boot - spring-boot-starter - ${spring-boot-starter.version} - - - net.openhft - chronicle-map - ${chronicle.map.version} - - - com.sun.java - tools - - + colt + colt + ${colt.version} + + org.springframework.boot + spring-boot-starter + ${spring-boot-starter.version} + + + net.openhft + chronicle-map + ${chronicle.map.version} + + + com.sun.java + tools + + + + + + + com.squareup.okhttp3 + okhttp + 3.14.2 + + + + com.fasterxml.jackson.core + jackson-databind + 2.9.9 + + + + com.google.code.gson + gson + 2.8.5 + + + + com.squareup.okhttp3 + mockwebserver + 3.14.2 + test + - - - com.squareup.okhttp3 - okhttp - 3.14.2 - - - com.fasterxml.jackson.core - jackson-databind - 2.9.9 - - - com.google.code.gson - gson - 2.8.5 - - - com.squareup.okhttp3 - mockwebserver - 3.14.2 - test - edu.uci.ics crawler4j ${crawler4j.version} - - - com.github.jknack - handlebars - 4.1.2 - - + - - 3.6.2 - 4.8.28 - 6.0.0.Final - 3.9.6 - 3.17.2 + + com.github.jknack + handlebars + 4.1.2 + + + + + org.openjdk.jmh + jmh-core + ${jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + + + + + + 3.6.2 + 4.8.28 + 6.0.0.Final + 3.9.6 + 3.17.2 4.4.0 - 2.1.4.RELEASE - + 2.1.4.RELEASE + 0.38 + 1.0.0-beta4 + 1.2.0 + 0.6.0 + 1.19 + diff --git a/libraries-2/src/test/java/com/baeldung/matrices/MatrixMultiplicationBenchmarking.java b/libraries-2/src/test/java/com/baeldung/matrices/MatrixMultiplicationBenchmarking.java new file mode 100644 index 0000000000..1e3b183aa7 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/matrices/MatrixMultiplicationBenchmarking.java @@ -0,0 +1,9 @@ +package com.baeldung.matrices; + +public class MatrixMultiplicationBenchmarking { + + public static void main(String[] args) throws Exception { + org.openjdk.jmh.Main.main(args); + } + +} diff --git a/libraries-2/src/test/java/com/baeldung/matrices/apache/RealMatrixUnitTest.java b/libraries-2/src/test/java/com/baeldung/matrices/apache/RealMatrixUnitTest.java new file mode 100644 index 0000000000..05944e7b3a --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/matrices/apache/RealMatrixUnitTest.java @@ -0,0 +1,47 @@ +package com.baeldung.matrices.apache; + +import org.apache.commons.math3.linear.Array2DRowRealMatrix; +import org.apache.commons.math3.linear.RealMatrix; +import org.junit.jupiter.api.Test; +import org.openjdk.jmh.annotations.*; + +import static org.assertj.core.api.Assertions.assertThat; + +@BenchmarkMode(Mode.AverageTime) +@Fork(value = 2) +@Warmup(iterations = 5) +@Measurement(iterations = 10) +public class RealMatrixUnitTest { + + @Test + @Benchmark + public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + RealMatrix firstMatrix = new Array2DRowRealMatrix( + new double[][] { + new double[] {1d, 5d}, + new double[] {2d, 3d}, + new double[] {1d ,7d} + } + ); + + RealMatrix secondMatrix = new Array2DRowRealMatrix( + new double[][] { + new double[] {1d, 2d, 3d, 7d}, + new double[] {5d, 2d, 8d, 1d} + } + ); + + RealMatrix expected = new Array2DRowRealMatrix( + new double[][] { + new double[] {26d, 12d, 43d, 12d}, + new double[] {17d, 10d, 30d, 17d}, + new double[] {36d, 16d, 59d, 14d} + } + ); + + RealMatrix actual = firstMatrix.multiply(secondMatrix); + + assertThat(actual).isEqualTo(expected); + } + +} diff --git a/libraries-2/src/test/java/com/baeldung/matrices/colt/DoubleMatrix2DUnitTest.java b/libraries-2/src/test/java/com/baeldung/matrices/colt/DoubleMatrix2DUnitTest.java new file mode 100644 index 0000000000..fb4a419eb0 --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/matrices/colt/DoubleMatrix2DUnitTest.java @@ -0,0 +1,51 @@ +package com.baeldung.matrices.colt; + +import cern.colt.matrix.DoubleFactory2D; +import cern.colt.matrix.DoubleMatrix2D; +import cern.colt.matrix.linalg.Algebra; +import org.junit.jupiter.api.Test; +import org.openjdk.jmh.annotations.*; + +import static org.assertj.core.api.Assertions.assertThat; + +@BenchmarkMode(Mode.AverageTime) +@Fork(value = 2) +@Warmup(iterations = 5) +@Measurement(iterations = 10) +public class DoubleMatrix2DUnitTest { + + @Test + @Benchmark + public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + DoubleFactory2D doubleFactory2D = DoubleFactory2D.dense; + + DoubleMatrix2D firstMatrix = doubleFactory2D.make( + new double[][] { + new double[] {1d, 5d}, + new double[] {2d, 3d}, + new double[] {1d ,7d} + } + ); + + DoubleMatrix2D secondMatrix = doubleFactory2D.make( + new double[][] { + new double[] {1d, 2d, 3d, 7d}, + new double[] {5d, 2d, 8d, 1d} + } + ); + + DoubleMatrix2D expected = doubleFactory2D.make( + new double[][] { + new double[] {26d, 12d, 43d, 12d}, + new double[] {17d, 10d, 30d, 17d}, + new double[] {36d, 16d, 59d, 14d} + } + ); + + Algebra algebra = new Algebra(); + DoubleMatrix2D actual = algebra.mult(firstMatrix, secondMatrix); + + assertThat(actual).isEqualTo(expected); + } + +} diff --git a/libraries-2/src/test/java/com/baeldung/matrices/ejml/SimpleMatrixUnitTest.java b/libraries-2/src/test/java/com/baeldung/matrices/ejml/SimpleMatrixUnitTest.java new file mode 100644 index 0000000000..b025266a1d --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/matrices/ejml/SimpleMatrixUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.matrices.ejml; + +import org.ejml.simple.SimpleMatrix; +import org.junit.jupiter.api.Test; +import org.openjdk.jmh.annotations.*; + +import static org.assertj.core.api.Assertions.assertThat; + +@BenchmarkMode(Mode.AverageTime) +@Fork(value = 2) +@Warmup(iterations = 5) +@Measurement(iterations = 10) +public class SimpleMatrixUnitTest { + + @Test + @Benchmark + public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + SimpleMatrix firstMatrix = new SimpleMatrix( + new double[][] { + new double[] {1d, 5d}, + new double[] {2d, 3d}, + new double[] {1d ,7d} + } + ); + + SimpleMatrix secondMatrix = new SimpleMatrix( + new double[][] { + new double[] {1d, 2d, 3d, 7d}, + new double[] {5d, 2d, 8d, 1d} + } + ); + + SimpleMatrix expected = new SimpleMatrix( + new double[][] { + new double[] {26d, 12d, 43d, 12d}, + new double[] {17d, 10d, 30d, 17d}, + new double[] {36d, 16d, 59d, 14d} + } + ); + + SimpleMatrix actual = firstMatrix.mult(secondMatrix); + + assertThat(actual).matches(m -> m.isIdentical(expected, 0d)); + } + +} diff --git a/libraries-2/src/test/java/com/baeldung/matrices/homemade/HomemadeMatrixUnitTest.java b/libraries-2/src/test/java/com/baeldung/matrices/homemade/HomemadeMatrixUnitTest.java new file mode 100644 index 0000000000..be9e483d5b --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/matrices/homemade/HomemadeMatrixUnitTest.java @@ -0,0 +1,58 @@ +package com.baeldung.matrices.homemade; + +import org.junit.jupiter.api.Test; +import org.openjdk.jmh.annotations.*; + +import static org.assertj.core.api.Assertions.assertThat; + +@BenchmarkMode(Mode.AverageTime) +@Fork(value = 2) +@Warmup(iterations = 5) +@Measurement(iterations = 10) +public class HomemadeMatrixUnitTest { + + @Test + @Benchmark + public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + double[][] firstMatrix = { + new double[]{1d, 5d}, + new double[]{2d, 3d}, + new double[]{1d, 7d} + }; + + double[][] secondMatrix = { + new double[]{1d, 2d, 3d, 7d}, + new double[]{5d, 2d, 8d, 1d} + }; + + double[][] expected = { + new double[]{26d, 12d, 43d, 12d}, + new double[]{17d, 10d, 30d, 17d}, + new double[]{36d, 16d, 59d, 14d} + }; + + double[][] actual = multiplyMatrices(firstMatrix, secondMatrix); + + assertThat(actual).isEqualTo(expected); + } + + private double[][] multiplyMatrices(double[][] firstMatrix, double[][] secondMatrix) { + double[][] result = new double[firstMatrix.length][secondMatrix[0].length]; + + for (int row = 0; row < result.length; row++) { + for (int col = 0; col < result[row].length; col++) { + result[row][col] = multiplyMatricesCell(firstMatrix, secondMatrix, row, col); + } + } + + return result; + } + + private double multiplyMatricesCell(double[][] firstMatrix, double[][] secondMatrix, int row, int col) { + double cell = 0; + for (int i = 0; i < secondMatrix.length; i++) { + cell += firstMatrix[row][i] * secondMatrix[i][col]; + } + return cell; + } +} diff --git a/libraries-2/src/test/java/com/baeldung/matrices/la4j/Basic2DMatrixUnitTest.java b/libraries-2/src/test/java/com/baeldung/matrices/la4j/Basic2DMatrixUnitTest.java new file mode 100644 index 0000000000..afb84ff3db --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/matrices/la4j/Basic2DMatrixUnitTest.java @@ -0,0 +1,47 @@ +package com.baeldung.matrices.la4j; + +import org.junit.jupiter.api.Test; +import org.la4j.Matrix; +import org.la4j.matrix.dense.Basic2DMatrix; +import org.openjdk.jmh.annotations.*; + +import static org.assertj.core.api.Assertions.assertThat; + +@BenchmarkMode(Mode.AverageTime) +@Fork(value = 2) +@Warmup(iterations = 5) +@Measurement(iterations = 10) +public class Basic2DMatrixUnitTest { + + @Test + @Benchmark + public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + Matrix firstMatrix = new Basic2DMatrix( + new double[][]{ + new double[]{1d, 5d}, + new double[]{2d, 3d}, + new double[]{1d, 7d} + } + ); + + Matrix secondMatrix = new Basic2DMatrix( + new double[][]{ + new double[]{1d, 2d, 3d, 7d}, + new double[]{5d, 2d, 8d, 1d} + } + ); + + Matrix expected = new Basic2DMatrix( + new double[][]{ + new double[]{26d, 12d, 43d, 12d}, + new double[]{17d, 10d, 30d, 17d}, + new double[]{36d, 16d, 59d, 14d} + } + ); + + Matrix actual = firstMatrix.multiply(secondMatrix); + + assertThat(actual).isEqualTo(expected); + } + +} diff --git a/libraries-2/src/test/java/com/baeldung/matrices/nd4j/INDArrayUnitTest.java b/libraries-2/src/test/java/com/baeldung/matrices/nd4j/INDArrayUnitTest.java new file mode 100644 index 0000000000..fb3030bccf --- /dev/null +++ b/libraries-2/src/test/java/com/baeldung/matrices/nd4j/INDArrayUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.matrices.nd4j; + +import org.junit.jupiter.api.Test; +import org.nd4j.linalg.api.ndarray.INDArray; +import org.nd4j.linalg.factory.Nd4j; +import org.openjdk.jmh.annotations.*; + +import static org.assertj.core.api.Assertions.assertThat; + +@BenchmarkMode(Mode.AverageTime) +@Fork(value = 2) +@Warmup(iterations = 5) +@Measurement(iterations = 10) +public class INDArrayUnitTest { + + @Test + public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + INDArray firstMatrix = Nd4j.create( + new double[][]{ + new double[]{1d, 5d}, + new double[]{2d, 3d}, + new double[]{1d, 7d} + } + ); + + INDArray secondMatrix = Nd4j.create( + new double[][] { + new double[] {1d, 2d, 3d, 7d}, + new double[] {5d, 2d, 8d, 1d} + } + ); + + INDArray expected = Nd4j.create( + new double[][] { + new double[] {26d, 12d, 43d, 12d}, + new double[] {17d, 10d, 30d, 17d}, + new double[] {36d, 16d, 59d, 14d} + } + ); + + INDArray actual = firstMatrix.mmul(secondMatrix); + + assertThat(actual).isEqualTo(expected); + } + +} diff --git a/libraries-server/pom.xml b/libraries-server/pom.xml index a6ead8fb31..873cca9b9b 100644 --- a/libraries-server/pom.xml +++ b/libraries-server/pom.xml @@ -96,6 +96,19 @@ smack-java7 ${smack.version} + + + + org.nanohttpd + nanohttpd + ${nanohttpd.version} + + + org.nanohttpd + nanohttpd-nanolets + ${nanohttpd.version} + + @@ -108,6 +121,7 @@ 8.5.24 4.3.1 1.2.0 + 2.3.1 \ No newline at end of file diff --git a/libraries-server/src/main/java/com/baeldung/nanohttpd/ApplicationController.java b/libraries-server/src/main/java/com/baeldung/nanohttpd/ApplicationController.java new file mode 100644 index 0000000000..2fa54c3ae2 --- /dev/null +++ b/libraries-server/src/main/java/com/baeldung/nanohttpd/ApplicationController.java @@ -0,0 +1,38 @@ +package com.baeldung.nanohttpd; + +import fi.iki.elonen.NanoHTTPD; +import fi.iki.elonen.router.RouterNanoHTTPD; + +import java.io.IOException; + +public class ApplicationController extends RouterNanoHTTPD { + + ApplicationController() throws IOException { + super(8072); + addMappings(); + start(NanoHTTPD.SOCKET_READ_TIMEOUT, false); + } + + @Override + public void addMappings() { + addRoute("/", IndexHandler.class); + addRoute("/users", UserHandler.class); + } + + public static class UserHandler extends DefaultHandler { + @Override + public String getText() { + return "UserA, UserB, UserC"; + } + + @Override + public String getMimeType() { + return MIME_PLAINTEXT; + } + + @Override + public Response.IStatus getStatus() { + return Response.Status.OK; + } + } +} \ No newline at end of file diff --git a/libraries-server/src/main/java/com/baeldung/nanohttpd/ItemGetController.java b/libraries-server/src/main/java/com/baeldung/nanohttpd/ItemGetController.java new file mode 100644 index 0000000000..4a9c48fbfd --- /dev/null +++ b/libraries-server/src/main/java/com/baeldung/nanohttpd/ItemGetController.java @@ -0,0 +1,22 @@ +package com.baeldung.nanohttpd; + +import fi.iki.elonen.NanoHTTPD; + +import java.io.IOException; + +public class ItemGetController extends NanoHTTPD { + + ItemGetController() throws IOException { + super(8071); + start(NanoHTTPD.SOCKET_READ_TIMEOUT, false); + } + + @Override + public Response serve(IHTTPSession session) { + if (session.getMethod() == Method.GET) { + String itemIdRequestParam = session.getParameters().get("itemId").get(0); + return newFixedLengthResponse("Requested itemId = " + itemIdRequestParam); + } + return newFixedLengthResponse(Response.Status.NOT_FOUND, MIME_PLAINTEXT, "The requested resource does not exist"); + } +} \ No newline at end of file diff --git a/libraries-server/src/test/java/com/baeldung/nanohttpd/ApplicationControllerUnitTest.java b/libraries-server/src/test/java/com/baeldung/nanohttpd/ApplicationControllerUnitTest.java new file mode 100644 index 0000000000..003f6ee3b7 --- /dev/null +++ b/libraries-server/src/test/java/com/baeldung/nanohttpd/ApplicationControllerUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.nanohttpd; + +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.HttpClientBuilder; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.Assert.*; + +public class ApplicationControllerUnitTest { + + private static final String BASE_URL = "http://localhost:8072/"; + private static final HttpClient CLIENT = HttpClientBuilder.create().build(); + + @BeforeClass + public static void setUp() throws IOException { + new ApplicationController(); + } + + @Test + public void givenServer_whenRootRouteRequested_thenHelloWorldReturned() throws IOException { + HttpResponse response = CLIENT.execute(new HttpGet(BASE_URL)); + assertTrue(IOUtils.toString(response.getEntity().getContent()).contains("Hello world!")); + assertEquals(200, response.getStatusLine().getStatusCode()); + } + + @Test + public void givenServer_whenUsersRequested_thenThenAllUsersReturned() throws IOException { + HttpResponse response = CLIENT.execute(new HttpGet(BASE_URL + "users")); + assertEquals("UserA, UserB, UserC", IOUtils.toString(response.getEntity().getContent())); + } +} \ No newline at end of file diff --git a/libraries-server/src/test/java/com/baeldung/nanohttpd/ItemGetControllerUnitTest.java b/libraries-server/src/test/java/com/baeldung/nanohttpd/ItemGetControllerUnitTest.java new file mode 100644 index 0000000000..3a4f0a4d98 --- /dev/null +++ b/libraries-server/src/test/java/com/baeldung/nanohttpd/ItemGetControllerUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.nanohttpd; + +import static org.junit.Assert.*; + +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.HttpClientBuilder; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; + +public class ItemGetControllerUnitTest { + + private static final String URL = "http://localhost:8071"; + private static final HttpClient CLIENT = HttpClientBuilder.create().build(); + + @BeforeClass + public static void setUp() throws IOException { + new ItemGetController(); + } + + @Test + public void givenServer_whenDoingGet_thenParamIsReadCorrectly() throws IOException { + HttpResponse response = CLIENT.execute(new HttpGet(URL + "?itemId=1234")); + assertEquals("Requested itemId = 1234", IOUtils.toString(response.getEntity().getContent())); + } + + @Test + public void givenServer_whenDoingPost_then404IsReturned() throws IOException { + HttpResponse response = CLIENT.execute(new HttpPost(URL)); + assertEquals(404, response.getStatusLine().getStatusCode()); + } +} \ No newline at end of file diff --git a/parent-boot-performance/README.md b/parent-boot-performance/README.md new file mode 100644 index 0000000000..fce9e101da --- /dev/null +++ b/parent-boot-performance/README.md @@ -0,0 +1 @@ +This is a parent module for projects that want to take advantage of the latest Spring Boot improvements/features. \ No newline at end of file diff --git a/parent-boot-performance/pom.xml b/parent-boot-performance/pom.xml new file mode 100644 index 0000000000..b1c6854eae --- /dev/null +++ b/parent-boot-performance/pom.xml @@ -0,0 +1,91 @@ + + 4.0.0 + parent-boot-performance + 0.0.1-SNAPSHOT + parent-boot-performance + pom + Parent for all modules that want to take advantage of the latest Spring Boot improvements/features. Current version: 2.2 + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + 3.1.0 + + 1.0.21.RELEASE + 2.2.0.M3 + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + io.rest-assured + rest-assured + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + ${start-class} + + + + + + + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + + + + + thin-jar + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.springframework.boot.experimental + spring-boot-thin-layout + ${thin.version} + + + + + + + + diff --git a/persistence-modules/java-jpa/pom.xml b/persistence-modules/java-jpa/pom.xml index f23040fbdc..51cc401332 100644 --- a/persistence-modules/java-jpa/pom.xml +++ b/persistence-modules/java-jpa/pom.xml @@ -19,6 +19,11 @@ hibernate-core ${hibernate.version} + + org.hibernate + hibernate-jpamodelgen + ${hibernate.version} + com.h2database h2 @@ -47,6 +52,58 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + -proc:none + + + + org.bsc.maven + maven-processor-plugin + 3.3.3 + + + process + + process + + generate-sources + + target/metamodel + + org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.0.0 + + + add-source + generate-sources + + add-source + + + + target/metamodel + + + + + + + 5.4.0.Final 2.7.4-RC1 diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/queryparams/Employee.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/queryparams/Employee.java new file mode 100644 index 0000000000..bf3d459530 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/queryparams/Employee.java @@ -0,0 +1,79 @@ +package com.baeldung.jpa.queryparams; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "employees") +public class Employee { + + /** + * + */ + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private Long id; + + @Column(name = "employee_number", unique = true) + private String empNumber; + + @Column(name = "employee_name") + private String name; + + @Column(name = "employee_age") + private int age; + + public Employee() { + super(); + } + + public Employee(Long id, String empNumber) { + super(); + this.id = id; + this.empNumber = empNumber; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmpNumber() { + return empNumber; + } + + public void setEmpNumber(String empNumber) { + this.empNumber = empNumber; + } + + public static long getSerialversionuid() { + return serialVersionUID; + } + +} 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 1f16bee3ba..6a236f0840 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 @@ -224,4 +224,26 @@ value="products_jpa.sql" /> + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.queryparams.Employee + true + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/queryparams/JPAQueryParamsUnitTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/queryparams/JPAQueryParamsUnitTest.java new file mode 100644 index 0000000000..4f320935cf --- /dev/null +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/queryparams/JPAQueryParamsUnitTest.java @@ -0,0 +1,109 @@ +package com.baeldung.jpa.queryparams; + +import java.util.Arrays; +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.ParameterExpression; +import javax.persistence.criteria.Root; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * JPAQueryParamsTest class tests. + * + * @author gmlopez.mackinnon@gmail.com + */ +public class JPAQueryParamsUnitTest { + + private static EntityManager entityManager; + + @BeforeClass + public static void setup() { + EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa-h2-queryparams"); + entityManager = factory.createEntityManager(); + } + + @Test + public void givenEmpNumber_whenUsingPositionalParameter_thenReturnExpectedEmployee() { + TypedQuery query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.empNumber = ?1", Employee.class); + String empNumber = "A123"; + Employee employee = query.setParameter(1, empNumber) + .getSingleResult(); + Assert.assertNotNull("Employee not found", employee); + } + + @Test + public void givenEmpNumberList_whenUsingPositionalParameter_thenReturnExpectedEmployee() { + TypedQuery query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.empNumber IN (?1)", Employee.class); + List empNumbers = Arrays.asList("A123", "A124"); + List employees = query.setParameter(1, empNumbers) + .getResultList(); + Assert.assertNotNull("Employees not found", employees); + Assert.assertFalse("Employees not found", employees.isEmpty()); + } + + @Test + public void givenEmpNumber_whenUsingNamedParameter_thenReturnExpectedEmployee() { + TypedQuery query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.empNumber = :number", Employee.class); + String empNumber = "A123"; + Employee employee = query.setParameter("number", empNumber) + .getSingleResult(); + Assert.assertNotNull("Employee not found", employee); + } + + @Test + public void givenEmpNumberList_whenUsingNamedParameter_thenReturnExpectedEmployee() { + TypedQuery query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.empNumber IN (:numbers)", Employee.class); + List empNumbers = Arrays.asList("A123", "A124"); + List employees = query.setParameter("numbers", empNumbers) + .getResultList(); + Assert.assertNotNull("Employees not found", employees); + Assert.assertFalse("Employees not found", employees.isEmpty()); + } + + @Test + public void givenEmpNameAndEmpAge_whenUsingTwoNamedParameters_thenReturnExpectedEmployees() { + TypedQuery query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.name = :name AND e.age = :empAge", Employee.class); + String empName = "John Doe"; + int empAge = 55; + List employees = query.setParameter("name", empName) + .setParameter("empAge", empAge) + .getResultList(); + Assert.assertNotNull("Employees not found!", employees); + Assert.assertTrue("Employees not found!", !employees.isEmpty()); + } + + @Test + public void givenEmpNumber_whenUsingCriteriaQuery_thenReturnExpectedEmployee() { + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + + CriteriaQuery cQuery = cb.createQuery(Employee.class); + Root c = cQuery.from(Employee.class); + ParameterExpression paramEmpNumber = cb.parameter(String.class); + cQuery.select(c) + .where(cb.equal(c.get(Employee_.empNumber), paramEmpNumber)); + + TypedQuery query = entityManager.createQuery(cQuery); + String empNumber = "A123"; + query.setParameter(paramEmpNumber, empNumber); + Employee employee = query.getSingleResult(); + Assert.assertNotNull("Employee not found!", employee); + } + + @Test + public void givenEmpNumber_whenUsingLiteral_thenReturnExpectedEmployee() { + String empNumber = "A123"; + TypedQuery query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.empNumber = '" + empNumber + "'", Employee.class); + Employee employee = query.getSingleResult(); + Assert.assertNotNull("Employee not found!", employee); + } + +} diff --git a/persistence-modules/java-jpa/src/test/resources/employees2.sql b/persistence-modules/java-jpa/src/test/resources/employees2.sql new file mode 100644 index 0000000000..d3ae46f6a0 --- /dev/null +++ b/persistence-modules/java-jpa/src/test/resources/employees2.sql @@ -0,0 +1,2 @@ +INSERT INTO employees (employee_number, employee_name, employee_age) VALUES ('111', 'John Doe', 55); +INSERT INTO employees (employee_number, employee_name, employee_age) VALUES ('A123', 'John Doe Junior', 25); \ No newline at end of file diff --git a/ratpack/build.gradle b/ratpack/build.gradle index 25af3ddb51..c997b4e697 100644 --- a/ratpack/build.gradle +++ b/ratpack/build.gradle @@ -14,6 +14,8 @@ if (!JavaVersion.current().java8Compatible) { apply plugin: "io.ratpack.ratpack-java" apply plugin: 'java' +apply plugin: 'groovy' +apply plugin: 'io.ratpack.ratpack-groovy' repositories { jcenter() diff --git a/ratpack/pom.xml b/ratpack/pom.xml index 7c145eff91..0df313c05e 100644 --- a/ratpack/pom.xml +++ b/ratpack/pom.xml @@ -26,11 +26,21 @@ ratpack-core ${ratpack.version} + + org.codehaus.groovy + groovy-sql + ${groovy.sql.version} + io.ratpack ratpack-hikari ${ratpack.version} + + io.ratpack + ratpack-groovy-test + ${ratpack.test.latest.version} + io.ratpack ratpack-hystrix @@ -91,6 +101,7 @@ 4.5.3 4.4.6 1.5.12 + 2.4.15 + 1.6.1 - diff --git a/ratpack/src/main/groovy/com/baeldung/Ratpack.groovy b/ratpack/src/main/groovy/com/baeldung/Ratpack.groovy new file mode 100644 index 0000000000..4d8814b627 --- /dev/null +++ b/ratpack/src/main/groovy/com/baeldung/Ratpack.groovy @@ -0,0 +1,76 @@ +package com.baeldung; + +@Grab('io.ratpack:ratpack-groovy:1.6.1') +import static ratpack.groovy.Groovy.ratpack + +import com.baeldung.model.User +import com.google.common.reflect.TypeToken +import ratpack.exec.Promise +import ratpack.handling.Context +import ratpack.jackson.Jackson +import groovy.sql.Sql +import java.sql.Connection +import java.sql.PreparedStatement +import java.sql.ResultSet +import ratpack.hikari.HikariModule +import javax.sql.DataSource; + +ratpack { + serverConfig { port(5050) } + bindings { + module(HikariModule) { config -> + config.dataSourceClassName = 'org.h2.jdbcx.JdbcDataSource' + config.addDataSourceProperty('URL', "jdbc:h2:mem:devDB;INIT=RUNSCRIPT FROM 'classpath:/User.sql'") + } + } + + handlers { + + get { render 'Hello World from Ratpack with Groovy!!' } + + get("greet/:name") { Context ctx -> + render "Hello " + ctx.getPathTokens().get("name") + "!!!" + } + + get("data") { + render Jackson.json([title: "Mr", name: "Norman", country: "USA"]) + } + + post("user") { + Promise user = parse(Jackson.fromJson(User)) + user.then { u -> render u.name } + } + + get('fetchUserName/:id') { Context ctx -> + Connection connection = ctx.get(DataSource.class).getConnection() + PreparedStatement queryStatement = connection.prepareStatement("SELECT NAME FROM USER WHERE ID=?") + queryStatement.setInt(1, Integer.parseInt(ctx.getPathTokens().get("id"))) + ResultSet resultSet = queryStatement.executeQuery() + resultSet.next() + render resultSet.getString(1) + } + + get('fetchUsers') { + def db = [url:'jdbc:h2:mem:devDB'] + def sql = Sql.newInstance(db.url, db.user, db.password) + def users = sql.rows("SELECT * FROM USER"); + render(Jackson.json(users)) + } + + post('addUser') { + parse(Jackson.fromJson(User)) + .then { u -> + def db = [url:'jdbc:h2:mem:devDB'] + Sql sql = Sql.newInstance(db.url, db.user, db.password) + sql.executeInsert("INSERT INTO USER VALUES (?,?,?,?)", [ + u.id, + u.title, + u.name, + u.country + ]) + render "User $u.name inserted" + } + } + } +} + diff --git a/ratpack/src/main/groovy/com/baeldung/RatpackGroovyApp.groovy b/ratpack/src/main/groovy/com/baeldung/RatpackGroovyApp.groovy new file mode 100644 index 0000000000..95ada25e60 --- /dev/null +++ b/ratpack/src/main/groovy/com/baeldung/RatpackGroovyApp.groovy @@ -0,0 +1,12 @@ +package com.baeldung; + +public class RatpackGroovyApp { + + public static void main(String[] args) { + File file = new File("src/main/groovy/com/baeldung/Ratpack.groovy"); + def shell = new GroovyShell() + shell.evaluate(file) + } + +} + diff --git a/ratpack/src/main/groovy/com/baeldung/model/User.groovy b/ratpack/src/main/groovy/com/baeldung/model/User.groovy new file mode 100644 index 0000000000..0fe4c6c367 --- /dev/null +++ b/ratpack/src/main/groovy/com/baeldung/model/User.groovy @@ -0,0 +1,9 @@ +package com.baeldung.model + +class User { + + long id + String title + String name + String country +} diff --git a/ratpack/src/main/resources/User.sql b/ratpack/src/main/resources/User.sql new file mode 100644 index 0000000000..a3e2242283 --- /dev/null +++ b/ratpack/src/main/resources/User.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS USER; +CREATE TABLE USER ( + ID BIGINT AUTO_INCREMENT PRIMARY KEY, + TITLE VARCHAR(255), + NAME VARCHAR(255), + COUNTRY VARCHAR(255) +); + +INSERT INTO USER VALUES(1,'Mr','Norman Potter', 'USA'); +INSERT INTO USER VALUES(2,'Miss','Ketty Smith', 'FRANCE'); \ No newline at end of file diff --git a/ratpack/src/test/groovy/com/baeldung/RatpackGroovySpec.groovy b/ratpack/src/test/groovy/com/baeldung/RatpackGroovySpec.groovy new file mode 100644 index 0000000000..726d703a06 --- /dev/null +++ b/ratpack/src/test/groovy/com/baeldung/RatpackGroovySpec.groovy @@ -0,0 +1,46 @@ +package com.baeldung; + +import ratpack.groovy.Groovy +import ratpack.groovy.test.GroovyRatpackMainApplicationUnderTest; +import ratpack.test.http.TestHttpClient; +import ratpack.test.ServerBackedApplicationUnderTest; +import org.junit.Test; +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import ratpack.test.MainClassApplicationUnderTest + +class RatpackGroovySpec { + + ServerBackedApplicationUnderTest ratpackGroovyApp = new MainClassApplicationUnderTest(RatpackGroovyApp.class) + @Delegate TestHttpClient client = TestHttpClient.testHttpClient(ratpackGroovyApp) + + @Test + void "test if app is started"() { + when: + get("") + + then: + assert response.statusCode == 200 + assert response.body.text == "Hello World from Ratpack with Groovy!!" + } + + @Test + void "test greet with name"() { + when: + get("greet/Lewis") + + then: + assert response.statusCode == 200 + assert response.body.text == "Hello Lewis!!!" + } + + @Test + void "test fetchUsers"() { + when: + get("fetchUsers") + + then: + assert response.statusCode == 200 + assert response.body.text == '[{"ID":1,"TITLE":"Mr","NAME":"Norman Potter","COUNTRY":"USA"},{"ID":2,"TITLE":"Miss","NAME":"Ketty Smith","COUNTRY":"FRANCE"}]' + } +} diff --git a/spring-5-data-reactive/pom.xml b/spring-5-data-reactive/pom.xml index aa73cf11ae..8c16851de0 100644 --- a/spring-5-data-reactive/pom.xml +++ b/spring-5-data-reactive/pom.xml @@ -63,6 +63,11 @@ spring-boot-starter-test test + + de.flapdoodle.embed + de.flapdoodle.embed.mongo + test + diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/LogsCounterApplication.java b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/LogsCounterApplication.java new file mode 100644 index 0000000000..8b2511a8f3 --- /dev/null +++ b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/LogsCounterApplication.java @@ -0,0 +1,11 @@ +package com.baeldung.tailablecursor; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class LogsCounterApplication { + public static void main(String[] args) { + SpringApplication.run(LogsCounterApplication.class, args); + } +} diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/domain/Log.java b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/domain/Log.java new file mode 100644 index 0000000000..717a367751 --- /dev/null +++ b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/domain/Log.java @@ -0,0 +1,21 @@ +package com.baeldung.tailablecursor.domain; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Data +@Document +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Log { + @Id + private String id; + private String service; + private LogLevel level; + private String message; +} diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/domain/LogLevel.java b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/domain/LogLevel.java new file mode 100644 index 0000000000..6826fbffd3 --- /dev/null +++ b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/domain/LogLevel.java @@ -0,0 +1,5 @@ +package com.baeldung.tailablecursor.domain; + +public enum LogLevel { + ERROR, WARN, INFO +} diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/repository/LogsRepository.java b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/repository/LogsRepository.java new file mode 100644 index 0000000000..dce11c548c --- /dev/null +++ b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/repository/LogsRepository.java @@ -0,0 +1,12 @@ +package com.baeldung.tailablecursor.repository; + +import com.baeldung.tailablecursor.domain.Log; +import com.baeldung.tailablecursor.domain.LogLevel; +import org.springframework.data.mongodb.repository.Tailable; +import org.springframework.data.repository.reactive.ReactiveCrudRepository; +import reactor.core.publisher.Flux; + +public interface LogsRepository extends ReactiveCrudRepository { + @Tailable + Flux findByLevel(LogLevel level); +} diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/ErrorLogsCounter.java b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/ErrorLogsCounter.java new file mode 100644 index 0000000000..c243e64f97 --- /dev/null +++ b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/ErrorLogsCounter.java @@ -0,0 +1,62 @@ +package com.baeldung.tailablecursor.service; + +import com.baeldung.tailablecursor.domain.Log; +import com.baeldung.tailablecursor.domain.LogLevel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.messaging.DefaultMessageListenerContainer; +import org.springframework.data.mongodb.core.messaging.MessageListener; +import org.springframework.data.mongodb.core.messaging.MessageListenerContainer; +import org.springframework.data.mongodb.core.messaging.TailableCursorRequest; + +import javax.annotation.PreDestroy; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.springframework.data.mongodb.core.query.Criteria.where; +import static org.springframework.data.mongodb.core.query.Query.query; + +@Slf4j +public class ErrorLogsCounter implements LogsCounter { + + private static final String LEVEL_FIELD_NAME = "level"; + + private final String collectionName; + private final MessageListenerContainer container; + + private final AtomicInteger counter = new AtomicInteger(); + + public ErrorLogsCounter(MongoTemplate mongoTemplate, + String collectionName) { + this.collectionName = collectionName; + this.container = new DefaultMessageListenerContainer(mongoTemplate); + + container.start(); + TailableCursorRequest request = getTailableCursorRequest(); + container.register(request, Log.class); + } + + @SuppressWarnings("unchecked") + private TailableCursorRequest getTailableCursorRequest() { + MessageListener listener = message -> { + log.info("ERROR log received: {}", message.getBody()); + counter.incrementAndGet(); + }; + + return TailableCursorRequest.builder() + .collection(collectionName) + .filter(query(where(LEVEL_FIELD_NAME).is(LogLevel.ERROR))) + .publishTo(listener) + .build(); + } + + @Override + public int count() { + return counter.get(); + } + + @PreDestroy + public void close() { + container.stop(); + } +} diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/InfoLogsCounter.java b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/InfoLogsCounter.java new file mode 100644 index 0000000000..b30eba0b25 --- /dev/null +++ b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/InfoLogsCounter.java @@ -0,0 +1,36 @@ +package com.baeldung.tailablecursor.service; + +import com.baeldung.tailablecursor.domain.Log; +import com.baeldung.tailablecursor.domain.LogLevel; +import com.baeldung.tailablecursor.repository.LogsRepository; +import lombok.extern.slf4j.Slf4j; +import reactor.core.Disposable; +import reactor.core.publisher.Flux; + +import javax.annotation.PreDestroy; +import java.util.concurrent.atomic.AtomicInteger; + +@Slf4j +public class InfoLogsCounter implements LogsCounter { + + private final AtomicInteger counter = new AtomicInteger(); + private final Disposable subscription; + + public InfoLogsCounter(LogsRepository repository) { + Flux stream = repository.findByLevel(LogLevel.INFO); + this.subscription = stream.subscribe(l -> { + log.info("INFO log received: " + l); + counter.incrementAndGet(); + }); + } + + @Override + public int count() { + return this.counter.get(); + } + + @PreDestroy + public void close() { + this.subscription.dispose(); + } +} diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/LogsCounter.java b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/LogsCounter.java new file mode 100644 index 0000000000..e14a3eadd7 --- /dev/null +++ b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/LogsCounter.java @@ -0,0 +1,5 @@ +package com.baeldung.tailablecursor.service; + +public interface LogsCounter { + int count(); +} diff --git a/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/WarnLogsCounter.java b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/WarnLogsCounter.java new file mode 100644 index 0000000000..b21f61fa88 --- /dev/null +++ b/spring-5-data-reactive/src/main/java/com/baeldung/tailablecursor/service/WarnLogsCounter.java @@ -0,0 +1,41 @@ +package com.baeldung.tailablecursor.service; + +import com.baeldung.tailablecursor.domain.Log; +import com.baeldung.tailablecursor.domain.LogLevel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.mongodb.core.ReactiveMongoTemplate; +import reactor.core.Disposable; +import reactor.core.publisher.Flux; + +import javax.annotation.PreDestroy; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.springframework.data.mongodb.core.query.Criteria.where; +import static org.springframework.data.mongodb.core.query.Query.query; + +@Slf4j +public class WarnLogsCounter implements LogsCounter { + + private static final String LEVEL_FIELD_NAME = "level"; + + private final AtomicInteger counter = new AtomicInteger(); + private final Disposable subscription; + + public WarnLogsCounter(ReactiveMongoTemplate template) { + Flux stream = template.tail(query(where(LEVEL_FIELD_NAME).is(LogLevel.WARN)), Log.class); + subscription = stream.subscribe(l -> { + log.warn("WARN log received: " + l); + counter.incrementAndGet(); + }); + } + + @Override + public int count() { + return counter.get(); + } + + @PreDestroy + public void close() { + subscription.dispose(); + } +} diff --git a/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/ErrorLogsCounterManualTest.java b/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/ErrorLogsCounterManualTest.java new file mode 100644 index 0000000000..5e20d3ec79 --- /dev/null +++ b/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/ErrorLogsCounterManualTest.java @@ -0,0 +1,112 @@ +package com.baeldung.tailablecursor.service; + +import com.baeldung.tailablecursor.domain.Log; +import com.baeldung.tailablecursor.domain.LogLevel; +import com.mongodb.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.CreateCollectionOptions; +import de.flapdoodle.embed.mongo.MongodExecutable; +import de.flapdoodle.embed.mongo.MongodProcess; +import de.flapdoodle.embed.mongo.MongodStarter; +import de.flapdoodle.embed.mongo.config.MongodConfigBuilder; +import de.flapdoodle.embed.mongo.config.Net; +import de.flapdoodle.embed.mongo.distribution.Version; +import de.flapdoodle.embed.process.runtime.Network; +import org.bson.Document; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.util.SocketUtils; + +import java.io.IOException; +import java.util.stream.IntStream; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +public class ErrorLogsCounterManualTest { + + private static final String SERVER = "localhost"; + private static final int PORT = SocketUtils.findAvailableTcpPort(10000); + private static final String DB_NAME = "test"; + private static final String COLLECTION_NAME = Log.class.getName().toLowerCase(); + + private static final MongodStarter starter = MongodStarter.getDefaultInstance(); + private static final int MAX_DOCUMENTS_IN_COLLECTION = 3; + + private ErrorLogsCounter errorLogsCounter; + private MongodExecutable mongodExecutable; + private MongodProcess mongoDaemon; + private MongoDatabase db; + + @Before + public void setup() throws Exception { + MongoTemplate mongoTemplate = initMongoTemplate(); + + MongoCollection collection = createCappedCollection(); + + persistDocument(collection, -1, LogLevel.ERROR, "my-service", "Initial log"); + + errorLogsCounter = new ErrorLogsCounter(mongoTemplate, COLLECTION_NAME); + Thread.sleep(1000L); // wait for initialization + } + + private MongoTemplate initMongoTemplate() throws IOException { + mongodExecutable = starter.prepare(new MongodConfigBuilder() + .version(Version.Main.PRODUCTION) + .net(new Net(SERVER, PORT, Network.localhostIsIPv6())) + .build()); + mongoDaemon = mongodExecutable.start(); + + MongoClient mongoClient = new MongoClient(SERVER, PORT); + db = mongoClient.getDatabase(DB_NAME); + + return new MongoTemplate(mongoClient, DB_NAME); + } + + private MongoCollection createCappedCollection() { + db.createCollection(COLLECTION_NAME, new CreateCollectionOptions() + .capped(true) + .sizeInBytes(100000) + .maxDocuments(MAX_DOCUMENTS_IN_COLLECTION)); + return db.getCollection(COLLECTION_NAME); + } + + private void persistDocument(MongoCollection collection, + int i, LogLevel level, String service, String message) { + Document logMessage = new Document(); + logMessage.append("_id", i); + logMessage.append("level", level.toString()); + logMessage.append("service", service); + logMessage.append("message", message); + collection.insertOne(logMessage); + } + + @After + public void tearDown() { + errorLogsCounter.close(); + mongoDaemon.stop(); + mongodExecutable.stop(); + } + + @Test + public void whenErrorLogsArePersisted_thenTheyAreReceivedByLogsCounter() throws Exception { + MongoCollection collection = db.getCollection(COLLECTION_NAME); + + IntStream.range(1, 10) + .forEach(i -> persistDocument(collection, + i, + i > 5 ? LogLevel.ERROR : LogLevel.INFO, + "service" + i, + "Message from service " + i) + ); + + Thread.sleep(1000L); // wait to receive all messages from the reactive mongodb driver + + assertThat(collection.countDocuments(), is((long) MAX_DOCUMENTS_IN_COLLECTION)); + assertThat(errorLogsCounter.count(), is(5)); + } + +} diff --git a/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/InfoLogsCounterManualTest.java b/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/InfoLogsCounterManualTest.java new file mode 100644 index 0000000000..cd8bd68257 --- /dev/null +++ b/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/InfoLogsCounterManualTest.java @@ -0,0 +1,75 @@ +package com.baeldung.tailablecursor.service; + +import com.baeldung.tailablecursor.LogsCounterApplication; +import com.baeldung.tailablecursor.domain.Log; +import com.baeldung.tailablecursor.domain.LogLevel; +import com.baeldung.tailablecursor.repository.LogsRepository; +import lombok.extern.slf4j.Slf4j; +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.data.mongodb.core.CollectionOptions; +import org.springframework.data.mongodb.core.ReactiveMongoTemplate; +import org.springframework.test.context.junit4.SpringRunner; +import reactor.core.publisher.Flux; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = LogsCounterApplication.class) +@Slf4j +public class InfoLogsCounterManualTest { + @Autowired + private LogsRepository repository; + + @Autowired + private ReactiveMongoTemplate template; + + @Before + public void setUp() { + createCappedCollectionUsingReactiveMongoTemplate(template); + + persistDocument(Log.builder() + .level(LogLevel.INFO) + .service("Service 2") + .message("Initial INFO message") + .build()); + } + + private void createCappedCollectionUsingReactiveMongoTemplate(ReactiveMongoTemplate reactiveMongoTemplate) { + reactiveMongoTemplate.dropCollection(Log.class).block(); + reactiveMongoTemplate.createCollection(Log.class, CollectionOptions.empty() + .maxDocuments(5) + .size(1024 * 1024L) + .capped()).block(); + } + + private void persistDocument(Log log) { + repository.save(log).block(); + } + + @Test + public void wheInfoLogsArePersisted_thenTheyAreReceivedByLogsCounter() throws Exception { + InfoLogsCounter infoLogsCounter = new InfoLogsCounter(repository); + + Thread.sleep(1000L); // wait for initialization + + Flux.range(0,10) + .map(i -> Log.builder() + .level(i > 5 ? LogLevel.WARN : LogLevel.INFO) + .service("some-service") + .message("some log message") + .build()) + .map(entity -> repository.save(entity).subscribe()) + .blockLast(); + + Thread.sleep(1000L); // wait to receive all messages from the reactive mongodb driver + + assertThat(infoLogsCounter.count(), is(7)); + infoLogsCounter.close(); + } +} \ No newline at end of file diff --git a/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/WarnLogsCounterManualTest.java b/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/WarnLogsCounterManualTest.java new file mode 100644 index 0000000000..79d94b6784 --- /dev/null +++ b/spring-5-data-reactive/src/test/java/com/baeldung/tailablecursor/service/WarnLogsCounterManualTest.java @@ -0,0 +1,75 @@ +package com.baeldung.tailablecursor.service; + +import com.baeldung.tailablecursor.LogsCounterApplication; +import com.baeldung.tailablecursor.domain.Log; +import com.baeldung.tailablecursor.domain.LogLevel; +import com.baeldung.tailablecursor.repository.LogsRepository; +import lombok.extern.slf4j.Slf4j; +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.data.mongodb.core.CollectionOptions; +import org.springframework.data.mongodb.core.ReactiveMongoTemplate; +import org.springframework.test.context.junit4.SpringRunner; +import reactor.core.publisher.Flux; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = LogsCounterApplication.class) +@Slf4j +public class WarnLogsCounterManualTest { + @Autowired + private LogsRepository repository; + + @Autowired + private ReactiveMongoTemplate template; + + @Before + public void setUp() { + createCappedCollectionUsingReactiveMongoTemplate(template); + + persistDocument(Log.builder() + .level(LogLevel.WARN) + .service("Service 1") + .message("Initial Warn message") + .build()); + } + + private void createCappedCollectionUsingReactiveMongoTemplate(ReactiveMongoTemplate reactiveMongoTemplate) { + reactiveMongoTemplate.dropCollection(Log.class).block(); + reactiveMongoTemplate.createCollection(Log.class, CollectionOptions.empty() + .maxDocuments(5) + .size(1024 * 1024L) + .capped()).block(); + } + + private void persistDocument(Log log) { + repository.save(log).block(); + } + + @Test + public void whenWarnLogsArePersisted_thenTheyAreReceivedByLogsCounter() throws Exception { + WarnLogsCounter warnLogsCounter = new WarnLogsCounter(template); + + Thread.sleep(1000L); // wait for initialization + + Flux.range(0,10) + .map(i -> Log.builder() + .level(i > 5 ? LogLevel.WARN : LogLevel.INFO) + .service("some-service") + .message("some log message") + .build()) + .map(entity -> repository.save(entity).subscribe()) + .blockLast(); + + Thread.sleep(1000L); // wait to receive all messages from the reactive mongodb driver + + assertThat(warnLogsCounter.count(), is(5)); + warnLogsCounter.close(); + } +} \ No newline at end of file diff --git a/spring-boot-performance/pom.xml b/spring-boot-performance/pom.xml new file mode 100644 index 0000000000..bbee7493cc --- /dev/null +++ b/spring-boot-performance/pom.xml @@ -0,0 +1,45 @@ + + 4.0.0 + spring-boot-performance + spring-boot-performance + war + This is a simple Spring Boot application taking advantage of the latest Spring Boot improvements/features. Current version: 2.2 + + + parent-boot-performance + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-performance + + + + + com.baeldung.lazyinitialization.Application + + + + + org.springframework.boot + spring-boot-starter + + + + + spring-boot-performance + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-war-plugin + + + + \ No newline at end of file diff --git a/spring-boot-performance/src/main/java/com/baeldung/lazyinitialization/Application.java b/spring-boot-performance/src/main/java/com/baeldung/lazyinitialization/Application.java new file mode 100644 index 0000000000..195b260399 --- /dev/null +++ b/spring-boot-performance/src/main/java/com/baeldung/lazyinitialization/Application.java @@ -0,0 +1,32 @@ +package com.baeldung.lazyinitialization; + +import com.baeldung.lazyinitialization.services.Writer; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class Application { + + @Bean("writer1") + public Writer getWriter1() { + return new Writer("Writer 1"); + } + + @Bean("writer2") + public Writer getWriter2() { + return new Writer("Writer 2"); + } + + public static void main(String[] args) { + ApplicationContext ctx = SpringApplication.run(Application.class, args); + System.out.println("Application context initialized!!!"); + + Writer writer1 = ctx.getBean("writer1", Writer.class); + writer1.write("First message"); + + Writer writer2 = ctx.getBean("writer2", Writer.class); + writer2.write("Second message"); + } +} diff --git a/spring-boot-performance/src/main/java/com/baeldung/lazyinitialization/services/Writer.java b/spring-boot-performance/src/main/java/com/baeldung/lazyinitialization/services/Writer.java new file mode 100644 index 0000000000..7c67fb7ea4 --- /dev/null +++ b/spring-boot-performance/src/main/java/com/baeldung/lazyinitialization/services/Writer.java @@ -0,0 +1,16 @@ +package com.baeldung.lazyinitialization.services; + +public class Writer { + + private final String writerId; + + public Writer(String writerId) { + this.writerId = writerId; + System.out.println(writerId + " initialized!!!"); + } + + public void write(String message) { + System.out.println(writerId + ": " + message); + } + +} diff --git a/spring-boot-performance/src/main/resources/application.yml b/spring-boot-performance/src/main/resources/application.yml new file mode 100644 index 0000000000..25f03eed56 --- /dev/null +++ b/spring-boot-performance/src/main/resources/application.yml @@ -0,0 +1,3 @@ +spring: + main: + lazy-initialization: true \ No newline at end of file diff --git a/spring-static-resources/pom.xml b/spring-static-resources/pom.xml index f01e807919..84519a37c1 100644 --- a/spring-static-resources/pom.xml +++ b/spring-static-resources/pom.xml @@ -140,6 +140,13 @@ handlebars ${handlebars.version} + + + + commons-io + commons-io + ${commons.io.version} + org.springframework @@ -208,6 +215,9 @@ 1.5.1 + + + 2.5 \ No newline at end of file diff --git a/spring-static-resources/src/main/java/com/baeldung/loadresourceasstring/LoadResourceConfig.java b/spring-static-resources/src/main/java/com/baeldung/loadresourceasstring/LoadResourceConfig.java new file mode 100644 index 0000000000..32b9ba84d0 --- /dev/null +++ b/spring-static-resources/src/main/java/com/baeldung/loadresourceasstring/LoadResourceConfig.java @@ -0,0 +1,15 @@ +package com.baeldung.loadresourceasstring; + + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class LoadResourceConfig { + + @Bean + public String resourceString() { + return ResourceReader.readFileToString("resource.txt"); + } + +} diff --git a/spring-static-resources/src/main/java/com/baeldung/loadresourceasstring/ResourceReader.java b/spring-static-resources/src/main/java/com/baeldung/loadresourceasstring/ResourceReader.java new file mode 100644 index 0000000000..7bc1babe91 --- /dev/null +++ b/spring-static-resources/src/main/java/com/baeldung/loadresourceasstring/ResourceReader.java @@ -0,0 +1,30 @@ +package com.baeldung.loadresourceasstring; + +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.util.FileCopyUtils; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UncheckedIOException; + +import static java.nio.charset.StandardCharsets.UTF_8; + + +public class ResourceReader { + + public static String readFileToString(String path) { + ResourceLoader resourceLoader = new DefaultResourceLoader(); + Resource resource = resourceLoader.getResource(path); + return asString(resource); + } + + public static String asString(Resource resource) { + try (Reader reader = new InputStreamReader(resource.getInputStream(), UTF_8)) { + return FileCopyUtils.copyToString(reader); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} diff --git a/spring-static-resources/src/main/resources/resource.txt b/spring-static-resources/src/main/resources/resource.txt new file mode 100644 index 0000000000..e78cfa90c2 --- /dev/null +++ b/spring-static-resources/src/main/resources/resource.txt @@ -0,0 +1 @@ +This is a resource text file. This file will be loaded as a resource and use its contents as a string. \ No newline at end of file diff --git a/spring-static-resources/src/test/java/com/baeldung/loadresourceasstring/LoadResourceAsStringIntegrationTest.java b/spring-static-resources/src/test/java/com/baeldung/loadresourceasstring/LoadResourceAsStringIntegrationTest.java new file mode 100644 index 0000000000..c16c1a9720 --- /dev/null +++ b/spring-static-resources/src/test/java/com/baeldung/loadresourceasstring/LoadResourceAsStringIntegrationTest.java @@ -0,0 +1,57 @@ +package com.baeldung.loadresourceasstring; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.convert.converter.Converter; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.util.FileCopyUtils; + +import java.io.InputStreamReader; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.assertEquals; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = LoadResourceConfig.class) +public class LoadResourceAsStringIntegrationTest { + + private static final String EXPECTED_RESOURCE_VALUE = "This is a resource text file. This file will be loaded as a " + "resource and use its contents as a string."; + + @Value("#{T(com.baeldung.loadresourceasstring.ResourceReader).readFileToString('classpath:resource.txt')}") + private String resourceStringUsingSpel; + + @Autowired + @Qualifier("resourceString") + private String resourceString; + + @Autowired + private ResourceLoader resourceLoader; + + @Test + public void givenUsingResourceLoadAndFileCopyUtils_whenConvertingAResourceToAString_thenCorrect() { + Resource resource = resourceLoader.getResource("classpath:resource.txt"); + assertEquals(EXPECTED_RESOURCE_VALUE, ResourceReader.asString(resource)); + } + + @Test + public void givenUsingResourceStringBean_whenConvertingAResourceToAString_thenCorrect() { + assertEquals(EXPECTED_RESOURCE_VALUE, resourceString); + } + + @Test + public void givenUsingSpel_whenConvertingAResourceToAString_thenCorrect() { + assertEquals(EXPECTED_RESOURCE_VALUE, resourceStringUsingSpel); + } + + + + +}